mirror of
https://github.com/github/codeql-action.git
synced 2026-11-13 00:05:27 +00:00
Compare commits
6 Commits
dependabot
...
mbg/add/cl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28638c7d60 | ||
|
|
c5be671f1f | ||
|
|
c29d405e42 | ||
|
|
8c16574468 | ||
|
|
3a4f195d36 | ||
|
|
2465f77e2e |
41
.github/actions/post-comment/action.yml
vendored
41
.github/actions/post-comment/action.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: "Post comment"
|
||||
description: "Create or update a sticky PR comment identified by a caller-provided marker."
|
||||
inputs:
|
||||
marker:
|
||||
description: >
|
||||
Non-empty plain-text identifier for the comment. Use a unique, stable value
|
||||
for each distinct comment; it is automatically wrapped in a hidden HTML comment.
|
||||
required: true
|
||||
body:
|
||||
description: "Full comment markdown."
|
||||
required: true
|
||||
update-only:
|
||||
description: Do nothing if no comment with the specified marker exists.
|
||||
required: false
|
||||
default: "false"
|
||||
issue-id:
|
||||
description: >
|
||||
The issue or pull request number to post/update the comment on.
|
||||
Defaults to the current pull request if not provided.
|
||||
required: false
|
||||
token:
|
||||
description: "The GitHub token to authenticate with."
|
||||
required: true
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Post comment
|
||||
shell: bash
|
||||
env:
|
||||
BODY: ${{ inputs.body }}
|
||||
MARKER: ${{ inputs.marker }}
|
||||
UPDATE_ONLY: ${{ case(inputs.update-only == 'true', '--update-only', '') }}
|
||||
GH_TOKEN: ${{ inputs.token }}
|
||||
ISSUE_ID: ${{ inputs.issue-id || github.event.pull_request.number }}
|
||||
run: |
|
||||
npx tsx ./pr-checks/post-comment.ts \
|
||||
--body "$BODY" \
|
||||
--marker "$MARKER" \
|
||||
$UPDATE_ONLY \
|
||||
--issue-id "$ISSUE_ID" \
|
||||
--repository "$GITHUB_REPOSITORY"
|
||||
9
.github/actions/prepare-test/action.yml
vendored
9
.github/actions/prepare-test/action.yml
vendored
@@ -36,14 +36,7 @@ runs:
|
||||
set -e # Fail this Action if `gh release list` fails.
|
||||
|
||||
if [[ "$VERSION" == "nightly" || "$VERSION" == "nightly-latest" ]]; then
|
||||
if [[ "$USE_ALL_PLATFORM_BUNDLE" == "true" ]]; then
|
||||
# With `tools: nightly`, the Action downloads the bundle for the runner's platform, so look
|
||||
# up the latest nightly release here to get its all-platform bundle instead.
|
||||
tag=$(gh release list --repo dsp-testing/codeql-cli-nightlies --limit 1 --json tagName --jq '.[0].tagName')
|
||||
echo "tools-url=https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/$tag/codeql-bundle.tar.gz" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "tools-url=nightly" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
echo "tools-url=nightly" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
elif [[ "$VERSION" == "linked" ]]; then
|
||||
echo "tools-url=linked" >> "$GITHUB_OUTPUT"
|
||||
|
||||
14
.github/workflows/__all-platform-bundle.yml
generated
vendored
14
.github/workflows/__all-platform-bundle.yml
generated
vendored
@@ -71,7 +71,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
@@ -92,18 +92,6 @@ jobs:
|
||||
# Swift is not supported on Ubuntu so we manually exclude it from the list here
|
||||
languages: cpp,csharp,go,java,javascript,python,ruby
|
||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||
- name: Check that the bundle contains tools for all platforms
|
||||
env:
|
||||
CODEQL_PATH: ${{ steps.init.outputs.codeql-path }}
|
||||
run: |
|
||||
# Platform-specific bundles only contain the tools for their own platform.
|
||||
tools_dir="$(dirname "$CODEQL_PATH")/tools"
|
||||
for platform in linux64 osx64 win64; do
|
||||
if [[ ! -d "$tools_dir/$platform" ]]; then
|
||||
echo "::error::Expected an all-platform CodeQL bundle, but '$tools_dir' does not contain a '$platform' directory."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
- name: Build code
|
||||
run: ./build.sh
|
||||
- uses: ./../action/analyze
|
||||
|
||||
2
.github/workflows/__analyze-ref-input.yml
generated
vendored
2
.github/workflows/__analyze-ref-input.yml
generated
vendored
@@ -67,7 +67,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__autobuild-action.yml
generated
vendored
2
.github/workflows/__autobuild-action.yml
generated
vendored
@@ -61,7 +61,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Prepare test
|
||||
|
||||
2
.github/workflows/__autobuild-direct-tracing-with-working-dir.yml
generated
vendored
2
.github/workflows/__autobuild-direct-tracing-with-working-dir.yml
generated
vendored
@@ -63,7 +63,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install Java
|
||||
uses: actions/setup-java@77dd5b2ce225ea11469928ac317850245a74ae78 # v6.2.0
|
||||
uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0
|
||||
with:
|
||||
java-version: ${{ inputs.java-version || '17' }}
|
||||
distribution: temurin
|
||||
|
||||
2
.github/workflows/__build-mode-autobuild.yml
generated
vendored
2
.github/workflows/__build-mode-autobuild.yml
generated
vendored
@@ -63,7 +63,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install Java
|
||||
uses: actions/setup-java@77dd5b2ce225ea11469928ac317850245a74ae78 # v6.2.0
|
||||
uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0
|
||||
with:
|
||||
java-version: ${{ inputs.java-version || '17' }}
|
||||
distribution: temurin
|
||||
|
||||
2
.github/workflows/__build-mode-manual.yml
generated
vendored
2
.github/workflows/__build-mode-manual.yml
generated
vendored
@@ -67,7 +67,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__export-file-baseline-information.yml
generated
vendored
2
.github/workflows/__export-file-baseline-information.yml
generated
vendored
@@ -71,7 +71,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__go-custom-queries.yml
generated
vendored
2
.github/workflows/__go-custom-queries.yml
generated
vendored
@@ -69,7 +69,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__linux-arm64.yml
generated
vendored
2
.github/workflows/__linux-arm64.yml
generated
vendored
@@ -67,7 +67,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__local-bundle.yml
generated
vendored
2
.github/workflows/__local-bundle.yml
generated
vendored
@@ -67,7 +67,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__multi-language-autodetect.yml
generated
vendored
2
.github/workflows/__multi-language-autodetect.yml
generated
vendored
@@ -101,7 +101,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__packaging-codescanning-config-inputs-js.yml
generated
vendored
2
.github/workflows/__packaging-codescanning-config-inputs-js.yml
generated
vendored
@@ -71,7 +71,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__packaging-config-inputs-js.yml
generated
vendored
2
.github/workflows/__packaging-config-inputs-js.yml
generated
vendored
@@ -71,7 +71,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__packaging-config-js.yml
generated
vendored
2
.github/workflows/__packaging-config-js.yml
generated
vendored
@@ -71,7 +71,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__packaging-inputs-js.yml
generated
vendored
2
.github/workflows/__packaging-inputs-js.yml
generated
vendored
@@ -71,7 +71,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__remote-config.yml
generated
vendored
2
.github/workflows/__remote-config.yml
generated
vendored
@@ -69,7 +69,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__split-workflow.yml
generated
vendored
2
.github/workflows/__split-workflow.yml
generated
vendored
@@ -77,7 +77,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__swift-custom-build.yml
generated
vendored
2
.github/workflows/__swift-custom-build.yml
generated
vendored
@@ -71,7 +71,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__unset-environment.yml
generated
vendored
2
.github/workflows/__unset-environment.yml
generated
vendored
@@ -69,7 +69,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__upload-ref-sha-input.yml
generated
vendored
2
.github/workflows/__upload-ref-sha-input.yml
generated
vendored
@@ -67,7 +67,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__upload-sarif.yml
generated
vendored
2
.github/workflows/__upload-sarif.yml
generated
vendored
@@ -74,7 +74,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
2
.github/workflows/__with-checkout-path.yml
generated
vendored
2
.github/workflows/__with-checkout-path.yml
generated
vendored
@@ -68,7 +68,7 @@ jobs:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
|
||||
- name: Install Go
|
||||
|
||||
1
.github/workflows/codeql.yml
vendored
1
.github/workflows/codeql.yml
vendored
@@ -79,6 +79,7 @@ jobs:
|
||||
- ubuntu-24.04
|
||||
- windows-2022
|
||||
- windows-2025
|
||||
- macos-14-xlarge
|
||||
- macos-15-xlarge
|
||||
tools: ${{ fromJson(needs.check-codeql-versions.outputs.versions) }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
with:
|
||||
go-version: ^1.13.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: "9.x"
|
||||
- name: Assert best-effort artifact scan completed
|
||||
|
||||
2
.github/workflows/debug-artifacts-safe.yml
vendored
2
.github/workflows/debug-artifacts-safe.yml
vendored
@@ -59,7 +59,7 @@ jobs:
|
||||
with:
|
||||
go-version: ^1.13.1
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: "9.x"
|
||||
- name: Assert best-effort artifact scan completed
|
||||
|
||||
1
.github/workflows/deflake.yml
vendored
1
.github/workflows/deflake.yml
vendored
@@ -31,6 +31,7 @@ on:
|
||||
- "PR Check - C/C\\+\\+: autoinstalling dependencies is skipped (macOS)"
|
||||
- "PR Check - C/C\\+\\+: disabling autoinstalling dependencies (Linux)"
|
||||
- "PR Check - Clean up database cluster directory"
|
||||
- "PR Check - CodeQL Bundle All"
|
||||
- "PR Check - Config export"
|
||||
- "PR Check - Config input"
|
||||
- "PR Check - Custom source root"
|
||||
|
||||
62
.github/workflows/test-codeql-bundle-all.yml
vendored
Normal file
62
.github/workflows/test-codeql-bundle-all.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: "PR Check - CodeQL Bundle All"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GO111MODULE: auto
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/v*
|
||||
pull_request:
|
||||
merge_group:
|
||||
types: [checks_requested]
|
||||
schedule:
|
||||
- cron: "0 5 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' || false }}
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
jobs:
|
||||
test-codeql-bundle-all:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-26.04
|
||||
version: nightly-latest
|
||||
name: "CodeQL Bundle All"
|
||||
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Prepare test
|
||||
id: prepare-test
|
||||
uses: ./.github/actions/prepare-test
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
use-all-platform-bundle: true
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
||||
with:
|
||||
dotnet-version: "9.x"
|
||||
- id: init
|
||||
uses: ./../action/init
|
||||
with:
|
||||
# We manually exclude Swift from the languages list here, as it is not supported on Ubuntu
|
||||
languages: cpp,csharp,go,java,javascript,python,ruby
|
||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||
- name: Build code
|
||||
run: ./build.sh
|
||||
- uses: ./../action/analyze
|
||||
env:
|
||||
CODEQL_ACTION_TEST_MODE: true
|
||||
@@ -6,10 +6,6 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.39.3 - 04 Nov 2026
|
||||
|
||||
- Fixed diff-informed alert filtering incorrectly removing alerts in changed files whose paths contain spaces, special characters, or non-ASCII characters. [#4283](https://github.com/github/codeql-action/pull/4283)
|
||||
|
||||
## 4.39.2 - 03 Nov 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.27.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.4). [#4284](https://github.com/github/codeql-action/pull/4284)
|
||||
|
||||
5228
lib/entry-points.js
generated
5228
lib/entry-points.js
generated
File diff suppressed because it is too large
Load Diff
370
package-lock.json
generated
370
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "codeql",
|
||||
"version": "4.39.4",
|
||||
"version": "4.39.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "codeql",
|
||||
"version": "4.39.4",
|
||||
"version": "4.39.3",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"pr-checks"
|
||||
@@ -33,6 +33,7 @@
|
||||
"js-yaml": "^5.5.0",
|
||||
"jsonschema": "1.5.0",
|
||||
"long": "^5.3.2",
|
||||
"minimatch": "^11.0.2",
|
||||
"node-forge": "^1.4.1",
|
||||
"semver": "^7.8.5",
|
||||
"undici": "^7.30.1",
|
||||
@@ -59,7 +60,7 @@
|
||||
"eslint-plugin-import-x": "^4.17.1",
|
||||
"eslint-plugin-jsdoc": "^65.4.0",
|
||||
"eslint-plugin-no-async-foreach": "^0.1.1",
|
||||
"glob": "^14.0.3",
|
||||
"glob": "^13.0.6",
|
||||
"globals": "^17.13.0",
|
||||
"nock": "^14.0.17",
|
||||
"prettier": "^3.9.10",
|
||||
@@ -564,6 +565,28 @@
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/glob/node_modules/brace-expansion": {
|
||||
"version": "1.1.21",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
|
||||
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/glob/node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz",
|
||||
@@ -1556,6 +1579,30 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-array/node_modules/brace-expansion": {
|
||||
"version": "1.1.21",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
|
||||
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-array/node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-helpers": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
|
||||
@@ -1619,6 +1666,17 @@
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
|
||||
"version": "1.1.21",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
|
||||
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/globals": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
|
||||
@@ -1655,6 +1713,19 @@
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.39.5",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz",
|
||||
@@ -1764,6 +1835,30 @@
|
||||
"node": ">=10.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
|
||||
"version": "1.1.21",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
|
||||
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/module-importer": {
|
||||
"version": "1.0.1",
|
||||
"dev": true,
|
||||
@@ -1905,6 +2000,17 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@microsoft/eslint-formatter-sarif/node_modules/brace-expansion": {
|
||||
"version": "1.1.21",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
|
||||
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@microsoft/eslint-formatter-sarif/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -2120,6 +2226,19 @@
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@microsoft/eslint-formatter-sarif/node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@mswjs/interceptors": {
|
||||
"version": "0.41.3",
|
||||
"resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.3.tgz",
|
||||
@@ -3008,29 +3127,6 @@
|
||||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
|
||||
"version": "5.0.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
|
||||
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
@@ -3530,6 +3626,7 @@
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -3539,6 +3636,7 @@
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
|
||||
"integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
@@ -4082,13 +4180,24 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.21",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
|
||||
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
|
||||
"version": "5.0.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
|
||||
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
"balanced-match": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion/node_modules/balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
@@ -4443,6 +4552,7 @@
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
@@ -4453,6 +4563,7 @@
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/comment-parser": {
|
||||
@@ -4489,6 +4600,8 @@
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/concordance": {
|
||||
@@ -4577,6 +4690,7 @@
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
@@ -4831,6 +4945,7 @@
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/es-abstract": {
|
||||
@@ -5377,29 +5492,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import-x/node_modules/balanced-match": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz",
|
||||
"integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import-x/node_modules/brace-expansion": {
|
||||
"version": "5.0.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
|
||||
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import-x/node_modules/minimatch": {
|
||||
"version": "10.2.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
|
||||
@@ -5416,6 +5508,17 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import/node_modules/brace-expansion": {
|
||||
"version": "1.1.21",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
|
||||
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import/node_modules/debug": {
|
||||
"version": "3.2.7",
|
||||
"dev": true,
|
||||
@@ -5424,6 +5527,19 @@
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import/node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsdoc": {
|
||||
"version": "65.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-65.4.0.tgz",
|
||||
@@ -5553,6 +5669,17 @@
|
||||
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": {
|
||||
"version": "1.1.21",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
|
||||
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
@@ -5560,6 +5687,19 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-no-async-foreach": {
|
||||
"version": "0.1.1",
|
||||
"dev": true,
|
||||
@@ -5674,6 +5814,17 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/brace-expansion": {
|
||||
"version": "1.1.21",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
|
||||
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/chalk": {
|
||||
"version": "4.1.0",
|
||||
"dev": true,
|
||||
@@ -5724,6 +5875,19 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
|
||||
@@ -6273,14 +6437,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "14.0.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-14.0.3.tgz",
|
||||
"integrity": "sha512-A1vjIwC3qpdCso45Iw127gnp7sPhqgY8lUQhDrArIs+GbmfaaVPFuoyy7WyLT9EPZCRZ7j7aLdwUhQmHWesEow==",
|
||||
"version": "13.0.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
|
||||
"integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"minimatch": "^11.0.2",
|
||||
"minimatch": "^10.2.2",
|
||||
"minipass": "^7.1.3",
|
||||
"path-scurry": "^3.0.0"
|
||||
"path-scurry": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
@@ -6302,35 +6466,13 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/brace-expansion": {
|
||||
"version": "5.0.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
|
||||
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/minimatch": {
|
||||
"version": "11.0.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-11.0.2.tgz",
|
||||
"integrity": "sha512-pWTgz5CN3tjqyZNSK2tePlSmu9IwM41q8yn8Usdqqwe9TIHh+9dEpLLjF4uApsfPEAZY71qtSiA2B2APEr+1Yw==",
|
||||
"version": "10.2.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
|
||||
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/nonrecursive-glob-match": "^1.0.2",
|
||||
"brace-expansion": "^5.0.12"
|
||||
"brace-expansion": "^5.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
@@ -6859,6 +7001,7 @@
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -7169,6 +7312,7 @@
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/js-string-escape": {
|
||||
@@ -7478,9 +7622,9 @@
|
||||
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "11.5.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz",
|
||||
"integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==",
|
||||
"version": "11.5.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz",
|
||||
"integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
@@ -8082,15 +8226,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"license": "ISC",
|
||||
"version": "11.0.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-11.0.2.tgz",
|
||||
"integrity": "sha512-pWTgz5CN3tjqyZNSK2tePlSmu9IwM41q8yn8Usdqqwe9TIHh+9dEpLLjF4uApsfPEAZY71qtSiA2B2APEr+1Yw==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
"@isaacs/nonrecursive-glob-match": "^1.0.2",
|
||||
"brace-expansion": "^5.0.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
"node": "18 || 20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
@@ -8571,6 +8719,7 @@
|
||||
},
|
||||
"node_modules/path-key": {
|
||||
"version": "3.1.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -8582,9 +8731,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-scurry": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-3.0.0.tgz",
|
||||
"integrity": "sha512-1pTbQqH1wIwMi/eleQ5leFTTCkzFsPcgXNjwOA8YGGW/W4/kHT3dssE7Z6NH+zuqNLOzOB0uaD61yl7cAcVhgg==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
|
||||
"integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^11.0.0",
|
||||
@@ -8800,27 +8949,6 @@
|
||||
"url": "https://github.com/sponsors/yqnn"
|
||||
}
|
||||
},
|
||||
"node_modules/readdir-glob/node_modules/balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/readdir-glob/node_modules/brace-expansion": {
|
||||
"version": "5.0.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
|
||||
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/readdir-glob/node_modules/minimatch": {
|
||||
"version": "10.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
|
||||
@@ -9170,6 +9298,7 @@
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
@@ -9180,6 +9309,7 @@
|
||||
},
|
||||
"node_modules/shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -9265,6 +9395,7 @@
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
@@ -9451,6 +9582,7 @@
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
@@ -9536,6 +9668,7 @@
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
@@ -10273,6 +10406,7 @@
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "codeql",
|
||||
"version": "4.39.4",
|
||||
"version": "4.39.3",
|
||||
"private": true,
|
||||
"description": "CodeQL action",
|
||||
"scripts": {
|
||||
@@ -43,6 +43,7 @@
|
||||
"js-yaml": "^5.5.0",
|
||||
"jsonschema": "1.5.0",
|
||||
"long": "^5.3.2",
|
||||
"minimatch": "^11.0.2",
|
||||
"node-forge": "^1.4.1",
|
||||
"semver": "^7.8.5",
|
||||
"undici": "^7.30.1",
|
||||
@@ -69,7 +70,7 @@
|
||||
"eslint-plugin-import-x": "^4.17.1",
|
||||
"eslint-plugin-jsdoc": "^65.4.0",
|
||||
"eslint-plugin-no-async-foreach": "^0.1.1",
|
||||
"glob": "^14.0.3",
|
||||
"glob": "^13.0.6",
|
||||
"globals": "^17.13.0",
|
||||
"nock": "^14.0.17",
|
||||
"prettier": "^3.9.10",
|
||||
@@ -96,7 +97,7 @@
|
||||
"eslint-plugin-jsx-a11y": {
|
||||
"semver": ">=6.3.1"
|
||||
},
|
||||
"glob": "^14.0.3",
|
||||
"glob": "^13.0.6",
|
||||
"undici": "^7.30.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,3 @@ export function getApiClient(token: string): ApiClient {
|
||||
const opts = githubUtils.getOctokitOptions(token);
|
||||
return new githubUtils.GitHub(opts);
|
||||
}
|
||||
|
||||
/** Resolves the GitHub API token to use, from `GH_TOKEN` or `GITHUB_TOKEN`. */
|
||||
export function resolveToken(env: NodeJS.ProcessEnv): string {
|
||||
const token = env.GH_TOKEN?.trim() || env.GITHUB_TOKEN?.trim();
|
||||
if (!token) {
|
||||
throw new Error(
|
||||
"Missing authentication token. Set GH_TOKEN or GITHUB_TOKEN.",
|
||||
);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
@@ -17,18 +17,6 @@ steps:
|
||||
# Swift is not supported on Ubuntu so we manually exclude it from the list here
|
||||
languages: cpp,csharp,go,java,javascript,python,ruby
|
||||
tools: ${{ steps.prepare-test.outputs.tools-url }}
|
||||
- name: Check that the bundle contains tools for all platforms
|
||||
env:
|
||||
CODEQL_PATH: ${{ steps.init.outputs.codeql-path }}
|
||||
run: |
|
||||
# Platform-specific bundles only contain the tools for their own platform.
|
||||
tools_dir="$(dirname "$CODEQL_PATH")/tools"
|
||||
for platform in linux64 osx64 win64; do
|
||||
if [[ ! -d "$tools_dir/$platform" ]]; then
|
||||
echo "::error::Expected an all-platform CodeQL bundle, but '$tools_dir' does not contain a '$platform' directory."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
- name: Build code
|
||||
run: ./build.sh
|
||||
- uses: ./../action/analyze
|
||||
|
||||
@@ -24,5 +24,3 @@ is:
|
||||
# PRs), so requiring them would block the PRs they don't run on.
|
||||
- "github-advanced-security"
|
||||
- "License compliance check"
|
||||
# Only runs when a PR is removed from the merge queue.
|
||||
- "Notify"
|
||||
|
||||
@@ -1,344 +0,0 @@
|
||||
#!/usr/bin/env npx tsx
|
||||
|
||||
/*
|
||||
Tests for post-comment.ts.
|
||||
*/
|
||||
|
||||
import * as assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
|
||||
import { type ApiClient, resolveToken } from "./api-client";
|
||||
import {
|
||||
findExistingComment,
|
||||
type Options,
|
||||
parseOptions,
|
||||
setComment,
|
||||
} from "./post-comment";
|
||||
|
||||
/** A baseline set of valid CLI flags, as an array, for use in parseOptions tests. */
|
||||
const validFlags = [
|
||||
"--body",
|
||||
"hello",
|
||||
"--marker",
|
||||
"marker",
|
||||
"--issue-id",
|
||||
"42",
|
||||
"--repository",
|
||||
"github/codeql-action",
|
||||
];
|
||||
|
||||
/** Returns a copy of `validFlags` with the value following `flag` replaced by `value`. */
|
||||
function withFlag(flag: string, value: string): string[] {
|
||||
const flags = [...validFlags];
|
||||
const index = flags.indexOf(flag);
|
||||
flags[index + 1] = value;
|
||||
return flags;
|
||||
}
|
||||
|
||||
/** Returns a copy of `validFlags` with `flag` (and its value) removed entirely. */
|
||||
function withoutFlag(flag: string): string[] {
|
||||
const flags = [...validFlags];
|
||||
const index = flags.indexOf(flag);
|
||||
flags.splice(index, 2);
|
||||
return flags;
|
||||
}
|
||||
|
||||
describe("parseOptions", async () => {
|
||||
await it("parses valid flags", () => {
|
||||
const options = parseOptions(validFlags);
|
||||
assert.deepEqual(options, {
|
||||
body: "hello",
|
||||
marker: "marker",
|
||||
updateOnly: false,
|
||||
issueId: 42,
|
||||
repository: { owner: "github", repo: "codeql-action" },
|
||||
});
|
||||
});
|
||||
|
||||
await it("enables update-only mode when --update-only is supplied", () => {
|
||||
const options = parseOptions([...validFlags, "--update-only"]);
|
||||
assert.equal(options.updateOnly, true);
|
||||
});
|
||||
|
||||
await it("rejects a missing --body", () => {
|
||||
assert.throws(
|
||||
() => parseOptions(withoutFlag("--body")),
|
||||
/Missing required flag --body/,
|
||||
);
|
||||
});
|
||||
|
||||
await it("rejects an empty --body", () => {
|
||||
assert.throws(
|
||||
() => parseOptions(withFlag("--body", "")),
|
||||
/The value for --body cannot be empty/,
|
||||
);
|
||||
});
|
||||
|
||||
await it("rejects a whitespace-only --body", () => {
|
||||
assert.throws(
|
||||
() => parseOptions(withFlag("--body", " \t\n")),
|
||||
/The value for --body cannot be empty/,
|
||||
);
|
||||
});
|
||||
|
||||
await it("rejects a missing --marker", () => {
|
||||
assert.throws(
|
||||
() => parseOptions(withoutFlag("--marker")),
|
||||
/Missing required flag --marker/,
|
||||
);
|
||||
});
|
||||
|
||||
await it("rejects an empty --marker", () => {
|
||||
assert.throws(
|
||||
() => parseOptions(withFlag("--marker", "")),
|
||||
/The value for --marker cannot be empty/,
|
||||
);
|
||||
});
|
||||
|
||||
await it("rejects a whitespace-only --marker", () => {
|
||||
assert.throws(
|
||||
() => parseOptions(withFlag("--marker", " \t\n")),
|
||||
/The value for --marker cannot be empty/,
|
||||
);
|
||||
});
|
||||
|
||||
await it("rejects a missing --repository", () => {
|
||||
assert.throws(
|
||||
() => parseOptions(withoutFlag("--repository")),
|
||||
/Missing required flag --repository/,
|
||||
);
|
||||
});
|
||||
|
||||
await it("rejects an empty --repository", () => {
|
||||
assert.throws(
|
||||
() => parseOptions(withFlag("--repository", "")),
|
||||
/The value for --repository cannot be empty/,
|
||||
);
|
||||
});
|
||||
|
||||
await it("rejects a whitespace-only --repository", () => {
|
||||
assert.throws(
|
||||
() => parseOptions(withFlag("--repository", " \t\n")),
|
||||
/The value for --repository cannot be empty/,
|
||||
);
|
||||
});
|
||||
|
||||
await it("rejects an invalid --repository value", () => {
|
||||
assert.throws(
|
||||
() => parseOptions(withFlag("--repository", "github/codeql/action")),
|
||||
/Invalid --repository value/,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveToken", async () => {
|
||||
await it("reads the token from GH_TOKEN", () => {
|
||||
assert.equal(
|
||||
resolveToken({ GH_TOKEN: "gh-token", GITHUB_TOKEN: "gha-token" }),
|
||||
"gh-token",
|
||||
);
|
||||
});
|
||||
|
||||
await it("falls back to GITHUB_TOKEN", () => {
|
||||
assert.equal(resolveToken({ GITHUB_TOKEN: "gha-token" }), "gha-token");
|
||||
});
|
||||
|
||||
await it("throws when no token is set", () => {
|
||||
assert.throws(() => resolveToken({}), /Missing authentication token/);
|
||||
});
|
||||
});
|
||||
|
||||
/** A minimal fake of the subset of `ApiClient` used by post-comment.ts. */
|
||||
function fakeClient(existingComments: Array<{ id: number; body?: string }>) {
|
||||
const comments = existingComments.map((comment) => ({ ...comment }));
|
||||
let nextId =
|
||||
comments.reduce((maxId, comment) => Math.max(maxId, comment.id), 0) + 1;
|
||||
|
||||
const client = {
|
||||
paginate: async () => comments,
|
||||
rest: {
|
||||
issues: {
|
||||
listComments: () => {},
|
||||
createComment: async ({ body }: { body: string }) => {
|
||||
comments.push({ id: nextId++, body });
|
||||
},
|
||||
updateComment: async ({
|
||||
comment_id,
|
||||
body,
|
||||
}: {
|
||||
comment_id: number;
|
||||
body: string;
|
||||
}) => {
|
||||
const comment = comments.find(({ id }) => id === comment_id);
|
||||
assert.ok(comment, `Comment ${comment_id} does not exist.`);
|
||||
comment.body = body;
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return { client: client as unknown as ApiClient, comments };
|
||||
}
|
||||
|
||||
describe("findExistingComment", async () => {
|
||||
await it("finds the id of the first comment containing the marker", async () => {
|
||||
const { client } = fakeClient([
|
||||
{ id: 1, body: "unrelated" },
|
||||
{ id: 2, body: "<!-- marker -->\nhello" },
|
||||
{ id: 3, body: "<!-- marker -->\nanother" },
|
||||
]);
|
||||
const id = await findExistingComment(
|
||||
client,
|
||||
{ owner: "owner", repo: "repo" },
|
||||
1,
|
||||
"marker",
|
||||
);
|
||||
assert.equal(id, 3);
|
||||
});
|
||||
|
||||
await it("returns undefined when no comment matches", async () => {
|
||||
const { client } = fakeClient([{ id: 1, body: "unrelated" }]);
|
||||
const id = await findExistingComment(
|
||||
client,
|
||||
{ owner: "owner", repo: "repo" },
|
||||
1,
|
||||
"marker",
|
||||
);
|
||||
assert.equal(id, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
/** A baseline set of `Options`, for use in `setComment` tests. */
|
||||
const baseOptions: Options = {
|
||||
body: "hello",
|
||||
marker: "marker",
|
||||
updateOnly: false,
|
||||
issueId: 42,
|
||||
repository: { owner: "owner", repo: "repo" },
|
||||
};
|
||||
|
||||
function assertCommentContent(
|
||||
comment: { body?: string },
|
||||
marker: string,
|
||||
body: string,
|
||||
): void {
|
||||
assert.ok(comment.body?.startsWith(`<!-- ${marker} -->`));
|
||||
assert.ok(comment.body?.endsWith(body));
|
||||
}
|
||||
|
||||
describe("setComment", async () => {
|
||||
await it("does not create a comment in update-only mode when none exists", async () => {
|
||||
const { client, comments } = fakeClient([]);
|
||||
|
||||
await setComment(client, { ...baseOptions, updateOnly: true });
|
||||
|
||||
// Resolution does not introduce a warning that was never posted.
|
||||
assert.deepEqual(comments, []);
|
||||
});
|
||||
|
||||
await it("leaves unrelated comments unchanged in update-only mode", async () => {
|
||||
const originalComments = [{ id: 7, body: "unrelated" }];
|
||||
const { client, comments } = fakeClient(originalComments);
|
||||
|
||||
await setComment(client, { ...baseOptions, updateOnly: true });
|
||||
|
||||
// Unrelated comments neither trigger resolution nor get overwritten.
|
||||
assert.deepEqual(comments, originalComments);
|
||||
});
|
||||
|
||||
await it("uses the supplied marker without affecting other comments", async () => {
|
||||
const marker = "custom-warning";
|
||||
const { client, comments } = fakeClient([
|
||||
{ id: 1, body: "<!-- marker -->\nunrelated warning" },
|
||||
{ id: 2, body: "<!-- custom-warning -->\nold warning" },
|
||||
]);
|
||||
const options = parseOptions(withFlag("--marker", marker));
|
||||
|
||||
await setComment(client, options);
|
||||
|
||||
// Only the comment with the supplied marker changes.
|
||||
assert.equal(comments.length, 2);
|
||||
assert.deepEqual(comments[0], {
|
||||
id: 1,
|
||||
body: "<!-- marker -->\nunrelated warning",
|
||||
});
|
||||
assert.equal(comments[1].id, 2);
|
||||
assertCommentContent(comments[1], marker, options.body);
|
||||
});
|
||||
|
||||
await it("creates a new comment with the marker prepended", async () => {
|
||||
const { client, comments } = fakeClient([]);
|
||||
// No comment has the marker before posting.
|
||||
assert.equal(comments.length, 0);
|
||||
assert.ok(
|
||||
!comments.some(({ body }) => body?.startsWith("<!-- marker -->")),
|
||||
);
|
||||
|
||||
await setComment(client, baseOptions);
|
||||
|
||||
// Posting adds exactly one comment with the marker before the body.
|
||||
assert.equal(comments.length, 1);
|
||||
assertCommentContent(comments[0], baseOptions.marker, baseOptions.body);
|
||||
});
|
||||
|
||||
await it("creates a new comment when no existing comment matches", async () => {
|
||||
const originalComments = [
|
||||
{ id: 7, body: "unrelated" },
|
||||
{ id: 2, body: "another unrelated comment" },
|
||||
];
|
||||
const { client, comments } = fakeClient(originalComments);
|
||||
// Existing comments do not match the marker.
|
||||
assert.ok(
|
||||
!comments.some(({ body }) => body?.startsWith("<!-- marker -->")),
|
||||
);
|
||||
|
||||
await setComment(client, baseOptions);
|
||||
|
||||
// A new comment is added without changing unrelated comments.
|
||||
assert.equal(comments.length, originalComments.length + 1);
|
||||
assert.deepEqual(
|
||||
comments.slice(0, originalComments.length),
|
||||
originalComments,
|
||||
);
|
||||
const markedComments = comments.filter(({ body }) =>
|
||||
body?.startsWith("<!-- marker -->"),
|
||||
);
|
||||
// Exactly one comment contains the expected marker and body.
|
||||
assert.equal(markedComments.length, 1);
|
||||
assertCommentContent(
|
||||
markedComments[0],
|
||||
baseOptions.marker,
|
||||
baseOptions.body,
|
||||
);
|
||||
// The new comment's ID does not collide with existing IDs.
|
||||
assert.equal(new Set(comments.map(({ id }) => id)).size, comments.length);
|
||||
});
|
||||
|
||||
await it("updates the existing comment when one is found", async () => {
|
||||
const { client, comments } = fakeClient([
|
||||
{ id: 7, body: "<!-- marker -->\nold" },
|
||||
]);
|
||||
|
||||
await setComment(client, baseOptions);
|
||||
|
||||
// Updating preserves the comment's ID without creating a duplicate.
|
||||
assert.equal(comments.length, 1);
|
||||
assert.equal(comments[0].id, 7);
|
||||
assertCommentContent(comments[0], baseOptions.marker, baseOptions.body);
|
||||
});
|
||||
|
||||
await it("replaces a warning with the resolved state using the same marker", async () => {
|
||||
const { client, comments } = fakeClient([
|
||||
{ id: 9, body: "<!-- marker -->\nold" },
|
||||
]);
|
||||
const body =
|
||||
"`CHANGELOG.md` is not modified in this PR. No changelog action is needed.";
|
||||
|
||||
await setComment(client, { ...baseOptions, body, updateOnly: true });
|
||||
|
||||
// The resolved state replaces the warning on the same marked comment.
|
||||
assert.equal(comments.length, 1);
|
||||
assert.equal(comments[0].id, 9);
|
||||
assertCommentContent(comments[0], baseOptions.marker, body);
|
||||
});
|
||||
});
|
||||
@@ -1,180 +0,0 @@
|
||||
#!/usr/bin/env npx tsx
|
||||
|
||||
/*
|
||||
Creates or updates a pull-request comment identified by a marker.
|
||||
|
||||
The marker is supplied via `--marker` and must be a non-empty plain-text identifier.
|
||||
The CLI wraps the marker in a hidden HTML comment, prepends it to `--body`,
|
||||
and uses it to find the comment on later runs.
|
||||
|
||||
Supply `--update-only` to suppress creation of comment; omit it
|
||||
to update or create comments.
|
||||
|
||||
Example:
|
||||
```sh
|
||||
GH_TOKEN=<token> npx tsx ./pr-checks/post-comment.ts \
|
||||
--body "The changelog needs updating." \
|
||||
--marker "my-bot" \
|
||||
--issue-id 123 \
|
||||
--repository github/codeql-action
|
||||
```
|
||||
*/
|
||||
|
||||
import assert from "node:assert/strict";
|
||||
import { parseArgs } from "node:util";
|
||||
|
||||
import { parseRepositoryNwo, type RepositoryNwo } from "../src/repository";
|
||||
|
||||
import { type ApiClient, getApiClient, resolveToken } from "./api-client";
|
||||
|
||||
/** Represents the command-line options. */
|
||||
export interface Options {
|
||||
/** The full comment body. */
|
||||
body: string;
|
||||
/** Plain-text identifier wrapped in a hidden HTML comment. */
|
||||
marker: string;
|
||||
/** Whether to only update a comment if a matching marker exists. */
|
||||
updateOnly: boolean;
|
||||
/** The issue/pull request number to post/update the comment on. */
|
||||
issueId: number;
|
||||
/** The repository to operate on. */
|
||||
repository: RepositoryNwo;
|
||||
}
|
||||
|
||||
function hiddenMarker(marker: string): string {
|
||||
return `<!-- ${marker} -->`;
|
||||
}
|
||||
|
||||
/** Parses CLI arguments supplied by the composite action into `Options`. */
|
||||
export function parseOptions(argv?: string[]): Options {
|
||||
const { values } = parseArgs({
|
||||
args: argv,
|
||||
options: {
|
||||
body: { type: "string" },
|
||||
marker: { type: "string" },
|
||||
"update-only": { type: "boolean", default: false },
|
||||
"issue-id": { type: "string" },
|
||||
repository: { type: "string" },
|
||||
},
|
||||
strict: true,
|
||||
});
|
||||
|
||||
assert(values.body !== undefined, "Missing required flag --body.");
|
||||
assert(values.body.trim() !== "", "The value for --body cannot be empty.");
|
||||
assert(values.marker !== undefined, "Missing required flag --marker.");
|
||||
assert(
|
||||
values.marker.trim() !== "",
|
||||
"The value for --marker cannot be empty.",
|
||||
);
|
||||
assert(
|
||||
values.repository !== undefined,
|
||||
"Missing required flag --repository.",
|
||||
);
|
||||
assert(
|
||||
values.repository.trim() !== "",
|
||||
"The value for --repository cannot be empty.",
|
||||
);
|
||||
assert(
|
||||
/^[\w.-]+\/[\w.-]+$/.test(values.repository),
|
||||
"Invalid --repository value.",
|
||||
);
|
||||
|
||||
return {
|
||||
body: values.body,
|
||||
marker: values.marker,
|
||||
updateOnly: values["update-only"],
|
||||
issueId: Number(values["issue-id"]),
|
||||
repository: parseRepositoryNwo(values.repository),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first comment on the given issue/pull request whose body starts with `marker`, if any.
|
||||
*/
|
||||
export async function findExistingComment(
|
||||
client: ApiClient,
|
||||
repository: RepositoryNwo,
|
||||
issueNumber: number,
|
||||
marker: string,
|
||||
): Promise<number | undefined> {
|
||||
const formattedMarker = hiddenMarker(marker);
|
||||
const comments = await client.paginate(client.rest.issues.listComments, {
|
||||
...repository,
|
||||
issue_number: issueNumber,
|
||||
per_page: 100,
|
||||
});
|
||||
const markedComments = comments.filter((comment) =>
|
||||
comment.body?.startsWith(formattedMarker),
|
||||
);
|
||||
if (markedComments.length > 1) {
|
||||
console.warn(
|
||||
`Found ${markedComments.length} comments with marker "${formattedMarker}". ` +
|
||||
"Updating the first one and leaving the others unchanged. " +
|
||||
"Use a unique marker for each distinct managed comment to avoid this situation.",
|
||||
);
|
||||
}
|
||||
return markedComments.at(-1)?.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates or updates a marked comment using `client` to talk to the GitHub API.
|
||||
*/
|
||||
export async function setComment(
|
||||
client: ApiClient,
|
||||
options: Options,
|
||||
): Promise<void> {
|
||||
const { issueId, marker, repository } = options;
|
||||
const body = `${hiddenMarker(marker)}\n${options.body}`;
|
||||
|
||||
const existingCommentId = await findExistingComment(
|
||||
client,
|
||||
repository,
|
||||
issueId,
|
||||
marker,
|
||||
);
|
||||
if (existingCommentId === undefined) {
|
||||
if (options.updateOnly) {
|
||||
console.info(
|
||||
"No existing comment found; skipping creation because --update-only was specified.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
console.info("No existing comment found; creating a new comment.");
|
||||
await client.rest.issues.createComment({
|
||||
...repository,
|
||||
issue_number: issueId,
|
||||
body,
|
||||
});
|
||||
} else {
|
||||
console.info(`Updating existing comment ${existingCommentId}.`);
|
||||
await client.rest.issues.updateComment({
|
||||
...repository,
|
||||
comment_id: existingCommentId,
|
||||
body,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function main(): Promise<number> {
|
||||
const options = parseOptions();
|
||||
|
||||
const token = resolveToken(process.env);
|
||||
const client = getApiClient(token);
|
||||
|
||||
await setComment(client, options);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
process.exit(await main());
|
||||
} catch (err) {
|
||||
console.error(err instanceof Error ? err.message : String(err));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
void run();
|
||||
}
|
||||
@@ -285,8 +285,8 @@ const languageSetups: LanguageSetups = {
|
||||
name: "Install Java",
|
||||
uses: pinnedUses(
|
||||
"actions/setup-java",
|
||||
"77dd5b2ce225ea11469928ac317850245a74ae78",
|
||||
"v6.2.0",
|
||||
"b843ebf9b913146b38da2eaa7aeddf76074ae1ad",
|
||||
"v6.1.0",
|
||||
),
|
||||
with: {
|
||||
"java-version": `\${{ inputs.java-version || '${defaultLanguageVersions.java}' }}`,
|
||||
@@ -320,8 +320,8 @@ const languageSetups: LanguageSetups = {
|
||||
name: "Install .NET",
|
||||
uses: pinnedUses(
|
||||
"actions/setup-dotnet",
|
||||
"0f4a354dd5547a28c70b7853dbd95d5b67886e73",
|
||||
"v6.1.0",
|
||||
"a98b56852c35b8e3190ac28c8c2271da59106c68",
|
||||
"v6.0.0",
|
||||
),
|
||||
with: {
|
||||
"dotnet-version": `\${{ inputs.dotnet-version || '${defaultLanguageVersions.csharp}' }}`,
|
||||
|
||||
@@ -78,12 +78,6 @@ export function getTemporaryDirectory(env: ReadOnlyEnv = getEnv()): string {
|
||||
);
|
||||
}
|
||||
|
||||
const PR_DIFF_RANGE_JSON_FILENAME = "pr-diff-range.json";
|
||||
|
||||
export function getDiffRangesJsonFilePath(env: Env = getEnv()): string {
|
||||
return path.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME);
|
||||
}
|
||||
|
||||
export function getActionVersion(): string {
|
||||
return __CODEQL_ACTION_VERSION__;
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ import {
|
||||
} from "./dependency-caching";
|
||||
import { addDiagnostic, makeDiagnostic } from "./diagnostics";
|
||||
import {
|
||||
DiffThunkRange,
|
||||
type DiffThunkRange,
|
||||
getDiffRangesJsonFilePath,
|
||||
readDiffRangesJsonFile,
|
||||
} from "./diff-informed-analysis-utils";
|
||||
} from "./diff-informed";
|
||||
import { EnvVar } from "./environment";
|
||||
import { FeatureEnablement, Feature } from "./feature-flags";
|
||||
import { getGitRoot } from "./git-utils";
|
||||
@@ -295,7 +296,10 @@ export async function setupDiffInformedQueryRun(
|
||||
return await withGroupAsync(
|
||||
"Generating diff range extension pack",
|
||||
async () => {
|
||||
const diffRanges = readDiffRangesJsonFile(logger);
|
||||
const diffRanges = readDiffRangesJsonFile(
|
||||
logger,
|
||||
getDiffRangesJsonFilePath(),
|
||||
);
|
||||
if (diffRanges === undefined) {
|
||||
logger.info(
|
||||
"No precomputed diff ranges found; skipping diff-informed analysis stage.",
|
||||
|
||||
@@ -15,6 +15,7 @@ import { createStubCodeQL } from "./codeql";
|
||||
import { UserConfig } from "./config/db-config";
|
||||
import * as file from "./config/file";
|
||||
import * as configUtils from "./config-utils";
|
||||
import { ActionsEnvVars } from "./environment";
|
||||
import * as errorMessages from "./error-messages";
|
||||
import { Feature } from "./feature-flags";
|
||||
import { RepositoryProperties } from "./feature-flags/properties";
|
||||
@@ -42,6 +43,7 @@ import {
|
||||
SAMPLE_DOTCOM_API_DETAILS,
|
||||
AssertableTarget,
|
||||
RecordingLogger,
|
||||
getTestEnv,
|
||||
} from "./testing-utils";
|
||||
import {
|
||||
GitHubVariant,
|
||||
@@ -151,9 +153,11 @@ function mockListLanguages(languages: string[]) {
|
||||
test.serial("load empty config", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const state = initAllState({ logger });
|
||||
|
||||
const languages = "javascript,python";
|
||||
|
||||
setupActionsVars(tempDir, tempDir);
|
||||
setupActionsVars(tempDir, tempDir, {}, state.env);
|
||||
|
||||
const codeql = createStubCodeQL({
|
||||
async resolveLanguages() {
|
||||
@@ -166,7 +170,6 @@ test.serial("load empty config", async (t) => {
|
||||
},
|
||||
});
|
||||
|
||||
const state = initAllState({ logger });
|
||||
const config = await configUtils.initConfig(
|
||||
state,
|
||||
createTestInitConfigInputs({
|
||||
@@ -197,9 +200,10 @@ test.serial("load empty config", async (t) => {
|
||||
test.serial("load code quality config", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const state = initAllState({ logger });
|
||||
const languages = "actions";
|
||||
|
||||
setupActionsVars(tempDir, tempDir);
|
||||
setupActionsVars(tempDir, tempDir, {}, state.env);
|
||||
|
||||
const codeql = createStubCodeQL({
|
||||
async resolveLanguages() {
|
||||
@@ -211,7 +215,6 @@ test.serial("load code quality config", async (t) => {
|
||||
},
|
||||
});
|
||||
|
||||
const state = initAllState({ logger });
|
||||
const config = await configUtils.initConfig(
|
||||
state,
|
||||
createTestInitConfigInputs({
|
||||
@@ -253,9 +256,10 @@ test.serial(
|
||||
async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const state = initAllState({ logger });
|
||||
const languages = "javascript";
|
||||
|
||||
setupActionsVars(tempDir, tempDir);
|
||||
setupActionsVars(tempDir, tempDir, {}, state.env);
|
||||
|
||||
const codeql = createStubCodeQL({
|
||||
async resolveLanguages() {
|
||||
@@ -291,7 +295,6 @@ test.serial(
|
||||
repositoryProperties,
|
||||
});
|
||||
|
||||
const state = initAllState({ logger });
|
||||
await t.notThrowsAsync(async () => {
|
||||
const config = await configUtils.initConfig(
|
||||
state,
|
||||
@@ -316,6 +319,8 @@ test.serial(
|
||||
test.serial("loading a saved config produces the same config", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const state = initAllState({ logger });
|
||||
setupActionsVars(tempDir, tempDir, {}, state.env);
|
||||
|
||||
const codeql = createStubCodeQL({
|
||||
async resolveLanguages() {
|
||||
@@ -334,7 +339,6 @@ test.serial("loading a saved config produces the same config", async (t) => {
|
||||
// Sanity check that getConfig returns undefined before we have called initConfig
|
||||
t.deepEqual(await configUtils.getConfig(tempDir, logger), undefined);
|
||||
|
||||
const state = initAllState({ logger });
|
||||
const config1 = await configUtils.initConfig(
|
||||
state,
|
||||
createTestInitConfigInputs({
|
||||
@@ -364,6 +368,8 @@ test.serial("loading a saved config produces the same config", async (t) => {
|
||||
test.serial("loading config with version mismatch throws", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
const logger = new RecordingLogger();
|
||||
const state = initAllState({ logger });
|
||||
setupActionsVars(tempDir, tempDir, {}, state.env);
|
||||
|
||||
const codeql = createStubCodeQL({
|
||||
async resolveLanguages() {
|
||||
@@ -387,7 +393,6 @@ test.serial("loading config with version mismatch throws", async (t) => {
|
||||
.stub(actionsUtil, "getActionVersion")
|
||||
.returns("does-not-exist");
|
||||
|
||||
const state = initAllState({ logger });
|
||||
const config = await configUtils.initConfig(
|
||||
state,
|
||||
createTestInitConfigInputs({
|
||||
@@ -497,7 +502,8 @@ const otherConfigFileContents = `
|
||||
|
||||
test.serial("load non-empty input", async (t) => {
|
||||
return await withTmpDir(async (tempDir) => {
|
||||
setupActionsVars(tempDir, tempDir);
|
||||
const state = initAllState();
|
||||
setupActionsVars(tempDir, tempDir, {}, state.env);
|
||||
|
||||
const codeql = createStubCodeQL({
|
||||
async resolveLanguages() {
|
||||
@@ -538,7 +544,6 @@ test.serial("load non-empty input", async (t) => {
|
||||
const languagesInput = "javascript";
|
||||
const configFilePath = createConfigFile(otherConfigFileContents, tempDir);
|
||||
|
||||
const state = initAllState();
|
||||
const actualConfig = await configUtils.initConfig(
|
||||
state,
|
||||
createTestInitConfigInputs({
|
||||
@@ -657,7 +662,9 @@ test.serial("API client used when reading remote config", async (t) => {
|
||||
const configFile = "octo-org/codeql-config/config.yaml@main";
|
||||
const languagesInput = "javascript";
|
||||
|
||||
const state = initAllState();
|
||||
const state = initAllState({
|
||||
env: getTestEnv({ [ActionsEnvVars.RUNNER_TEMP]: tempDir }),
|
||||
});
|
||||
await configUtils.initConfig(
|
||||
state,
|
||||
createTestInitConfigInputs({
|
||||
|
||||
@@ -48,7 +48,10 @@ import {
|
||||
addNoLanguageDiagnostic,
|
||||
makeTelemetryDiagnostic,
|
||||
} from "./diagnostics";
|
||||
import { prepareDiffInformedAnalysis } from "./diff-informed-analysis-utils";
|
||||
import {
|
||||
getDiffRangesJsonFilePath,
|
||||
prepareDiffInformedAnalysis,
|
||||
} from "./diff-informed";
|
||||
import { EnvVar, exportEnvVar, getEnv } from "./environment";
|
||||
import * as errorMessages from "./error-messages";
|
||||
import { Feature, FeatureEnablement, FeatureWithoutCLI } from "./feature-flags";
|
||||
@@ -1288,9 +1291,10 @@ export async function initConfig(
|
||||
}
|
||||
|
||||
const hasDiffRanges = await prepareDiffInformedAnalysis(
|
||||
inputs.codeql,
|
||||
inputs.features,
|
||||
logger,
|
||||
inputs.features,
|
||||
inputs.codeql,
|
||||
getDiffRangesJsonFilePath(actionState.env),
|
||||
);
|
||||
|
||||
await applyIncrementalAnalysisSettings(
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
import test, { ExecutionContext } from "ava";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import type { PullRequestBranches } from "./actions-util";
|
||||
import * as apiClient from "./api-client";
|
||||
import {
|
||||
getDiffInformedAnalysisBranches,
|
||||
prepareDiffInformedAnalysis,
|
||||
exportedForTesting,
|
||||
} from "./diff-informed-analysis-utils";
|
||||
import { Feature, FeatureEnablement, initFeatures } from "./feature-flags";
|
||||
import { parseRepositoryNwo } from "./repository";
|
||||
import * as actionsUtil from "../actions-util";
|
||||
import type { PullRequestBranches } from "../actions-util";
|
||||
import * as apiClient from "../api-client";
|
||||
import { getEnv } from "../environment";
|
||||
import { Feature, FeatureEnablement, initFeatures } from "../feature-flags";
|
||||
import { parseRepositoryNwo } from "../repository";
|
||||
import {
|
||||
setupTests,
|
||||
createFeatures,
|
||||
@@ -19,9 +15,16 @@ import {
|
||||
setupActionsVars,
|
||||
makeMacro,
|
||||
RecordingLogger,
|
||||
} from "./testing-utils";
|
||||
import { GitHubVariant, withTmpDir } from "./util";
|
||||
import type { GitHubVersion } from "./util";
|
||||
} from "../testing-utils";
|
||||
import { GitHubVariant, withTmpDir } from "../util";
|
||||
import type { GitHubVersion } from "../util";
|
||||
|
||||
import {
|
||||
getDiffInformedAnalysisBranches,
|
||||
prepareDiffInformedAnalysis,
|
||||
exportedForTesting,
|
||||
getDiffRangesJsonFilePath,
|
||||
} from ".";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
@@ -192,9 +195,10 @@ test.serial(
|
||||
.resolves({ type: GitHubVariant.DOTCOM });
|
||||
|
||||
const result = await prepareDiffInformedAnalysis(
|
||||
codeql,
|
||||
features,
|
||||
logger,
|
||||
features,
|
||||
codeql,
|
||||
getDiffRangesJsonFilePath(getEnv()),
|
||||
);
|
||||
|
||||
t.false(result);
|
||||
@@ -222,9 +226,10 @@ test.serial(
|
||||
};
|
||||
|
||||
const result = await prepareDiffInformedAnalysis(
|
||||
codeql,
|
||||
features,
|
||||
logger,
|
||||
features,
|
||||
codeql,
|
||||
getDiffRangesJsonFilePath(getEnv()),
|
||||
);
|
||||
|
||||
t.false(result);
|
||||
@@ -259,9 +264,10 @@ test.serial(
|
||||
} as any);
|
||||
|
||||
const result = await prepareDiffInformedAnalysis(
|
||||
codeql,
|
||||
features,
|
||||
logger,
|
||||
features,
|
||||
codeql,
|
||||
getDiffRangesJsonFilePath(getEnv()),
|
||||
);
|
||||
|
||||
t.true(result);
|
||||
@@ -296,9 +302,10 @@ test.serial(
|
||||
} as any);
|
||||
|
||||
const result = await prepareDiffInformedAnalysis(
|
||||
codeql,
|
||||
features,
|
||||
logger,
|
||||
features,
|
||||
codeql,
|
||||
getDiffRangesJsonFilePath(getEnv()),
|
||||
);
|
||||
|
||||
t.false(result);
|
||||
@@ -1,23 +1,43 @@
|
||||
import * as fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import type { PullRequestBranches } from "./actions-util";
|
||||
import { getApiClient, getGitHubVersion } from "./api-client";
|
||||
import type { CodeQL } from "./codeql";
|
||||
import { Feature, FeatureEnablement } from "./feature-flags";
|
||||
import { Logger } from "./logging";
|
||||
import { getRepositoryNwoFromEnv } from "./repository";
|
||||
import { getErrorMessage, GitHubVariant, satisfiesGHESVersion } from "./util";
|
||||
import * as actionsUtil from "../actions-util";
|
||||
import type { PullRequestBranches } from "../actions-util";
|
||||
import { getApiClient, getGitHubVersion } from "../api-client";
|
||||
import type { CodeQL } from "../codeql";
|
||||
import { type Env, getEnv } from "../environment";
|
||||
import type { FeatureEnablement } from "../feature-flags";
|
||||
import { Feature } from "../feature-flags/features";
|
||||
import { Logger } from "../logging";
|
||||
import { getRepositoryNwoFromEnv } from "../repository";
|
||||
import { getErrorMessage, GitHubVariant, satisfiesGHESVersion } from "../util";
|
||||
|
||||
/** The filename used to persist PR diff ranges. */
|
||||
const PR_DIFF_RANGE_JSON_FILENAME = "pr-diff-range.json";
|
||||
|
||||
/**
|
||||
* Gets the full path of the file used to persist PR diff ranges.
|
||||
*/
|
||||
export function getDiffRangesJsonFilePath(env: Env = getEnv()): string {
|
||||
return path.join(
|
||||
actionsUtil.getTemporaryDirectory(env),
|
||||
PR_DIFF_RANGE_JSON_FILENAME,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface is an abbreviated version of the file diff object returned by
|
||||
* the GitHub API.
|
||||
*/
|
||||
interface FileDiff {
|
||||
export interface FileDiff {
|
||||
/** The name of the file that has changed. */
|
||||
filename: string;
|
||||
/** The number of changes. */
|
||||
changes: number;
|
||||
// A patch may be absent if the file is binary, if the file diff is too large,
|
||||
// or if the file is unchanged.
|
||||
/**
|
||||
* The diff, if available. It may be absent if the file is binary, if the file diff is too large,
|
||||
* or if the file is unchanged.
|
||||
*/
|
||||
patch?: string | undefined;
|
||||
}
|
||||
|
||||
@@ -63,9 +83,10 @@ export async function getDiffInformedAnalysisBranches(
|
||||
* and are therefore available for use, `false` otherwise.
|
||||
*/
|
||||
export async function prepareDiffInformedAnalysis(
|
||||
codeql: CodeQL,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger,
|
||||
features: FeatureEnablement,
|
||||
codeql: CodeQL,
|
||||
jsonFilePath: string,
|
||||
): Promise<boolean> {
|
||||
let branches: PullRequestBranches | undefined;
|
||||
try {
|
||||
@@ -84,7 +105,7 @@ export async function prepareDiffInformedAnalysis(
|
||||
}
|
||||
|
||||
try {
|
||||
return await computeAndPersistDiffRanges(branches, logger);
|
||||
return await computeAndPersistDiffRanges(logger, jsonFilePath, branches);
|
||||
} catch (e) {
|
||||
logger.warning(
|
||||
`Failed to compute diff-informed analysis ranges: ${getErrorMessage(e)}`,
|
||||
@@ -93,29 +114,45 @@ export async function prepareDiffInformedAnalysis(
|
||||
}
|
||||
}
|
||||
|
||||
/** Describes a changed line range in a file. */
|
||||
export interface DiffThunkRange {
|
||||
/** Relative path from the repository root, using forward slashes as separators. */
|
||||
path: string;
|
||||
/** The starting line of the change (1-based and inclusive). */
|
||||
startLine: number;
|
||||
/** The last line of the change (1-based and inclusive). */
|
||||
endLine: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an array of {@link DiffThunkRange} objects to the file given by {@link jsonFilePath}.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @param jsonFilePath The path of the file to write.
|
||||
* @param ranges The changed line ranges to write.
|
||||
*/
|
||||
export function writeDiffRangesJsonFile(
|
||||
logger: Logger,
|
||||
jsonFilePath: string,
|
||||
ranges: DiffThunkRange[],
|
||||
): void {
|
||||
const jsonContents = JSON.stringify(ranges, null, 2);
|
||||
const jsonFilePath = actionsUtil.getDiffRangesJsonFilePath();
|
||||
fs.writeFileSync(jsonFilePath, jsonContents);
|
||||
logger.debug(
|
||||
`Wrote pr-diff-range JSON file to ${jsonFilePath}:\n${jsonContents}`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an array of {@link DiffThunkRange} objects from the file given by {@link jsonFilePath}.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @returns The array of {@link DiffThunkRange} objects or `undefined` if the file couldn't be read.
|
||||
*/
|
||||
export function readDiffRangesJsonFile(
|
||||
logger: Logger,
|
||||
jsonFilePath: string,
|
||||
): DiffThunkRange[] | undefined {
|
||||
const jsonFilePath = actionsUtil.getDiffRangesJsonFilePath();
|
||||
if (!fs.existsSync(jsonFilePath)) {
|
||||
logger.debug(`Diff ranges JSON file does not exist at ${jsonFilePath}`);
|
||||
return undefined;
|
||||
@@ -138,12 +175,12 @@ export function readDiffRangesJsonFile(
|
||||
* Return the file line ranges that were added or modified in the pull request.
|
||||
*
|
||||
* @param branches The base and head branches of the pull request.
|
||||
* @param logger
|
||||
* @returns An array of tuples, where each tuple contains the relative path of a
|
||||
* file (relative to the repository root, as returned by the GitHub compare API),
|
||||
* the start line and the end line (both 1-based and inclusive) of an
|
||||
* added or modified range in that file. Returns `undefined` if the action was
|
||||
* not triggered by a pull request or if there was an error.
|
||||
* @param logger The logger to use.
|
||||
*
|
||||
* @returns
|
||||
* An array of {@link DiffThunkRange} objects, where each describes a line range in a file
|
||||
* that was changed in the pull request described by {@link branches} or `undefined` if
|
||||
* we were unable to compute them.
|
||||
*/
|
||||
export async function getPullRequestEditedDiffRanges(
|
||||
branches: PullRequestBranches,
|
||||
@@ -180,22 +217,25 @@ export async function getPullRequestEditedDiffRanges(
|
||||
* diff from the GitHub API and writes it to the diff ranges JSON file so that
|
||||
* CodeQL can use it for diff-informed analysis.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @param jsonFilePath The path of the JSON file to write.
|
||||
* @param branches The base and head branches of the pull request, as returned
|
||||
* by `getDiffInformedAnalysisBranches`.
|
||||
* @param logger
|
||||
*
|
||||
* @returns `true` if the diff ranges were successfully computed and persisted,
|
||||
* otherwise `false`.
|
||||
*/
|
||||
export async function computeAndPersistDiffRanges(
|
||||
branches: PullRequestBranches,
|
||||
logger: Logger,
|
||||
jsonFilePath: string,
|
||||
branches: PullRequestBranches,
|
||||
): Promise<boolean> {
|
||||
logger.info("Computing PR diff ranges...");
|
||||
const ranges = await getPullRequestEditedDiffRanges(branches, logger);
|
||||
if (ranges === undefined) {
|
||||
return false;
|
||||
}
|
||||
writeDiffRangesJsonFile(logger, ranges);
|
||||
writeDiffRangesJsonFile(logger, jsonFilePath, ranges);
|
||||
const distinctFiles = new Set(ranges.map((r) => r.path)).size;
|
||||
logger.info(
|
||||
`Persisted ${ranges.length} diff range(s) across ${distinctFiles} file(s).`,
|
||||
@@ -203,6 +243,19 @@ export async function computeAndPersistDiffRanges(
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an array of {@link FileDiff} objects using the GitHub API describing the changed files
|
||||
* in the pull request with the base and head refs given by {@link branches}.
|
||||
*
|
||||
* @param branches The pull request branch refs.
|
||||
* @param logger The logger to use.
|
||||
*
|
||||
* @throws Non-HTTP errors that occur while fetching the file diffs.
|
||||
*
|
||||
* @returns
|
||||
* An array of {@link FileDiff} objects describing the changed files in the PR, or
|
||||
* `undefined` if we couldn't obtain the changed files from the API.
|
||||
*/
|
||||
async function getFileDiffsWithBasehead(
|
||||
branches: PullRequestBranches,
|
||||
logger: Logger,
|
||||
@@ -243,6 +296,16 @@ async function getFileDiffsWithBasehead(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts an array of {@link DiffThunkRange} objects from {@link fileDiff}.
|
||||
*
|
||||
* @param fileDiff The {@link FileDiff} object describing changes to a particular file.
|
||||
* @param logger The logger to use.
|
||||
*
|
||||
* @returns
|
||||
* The {@link DiffThunkRange} objects extracted from {@link fileDiff},
|
||||
* or `undefined` if there are none that could be extracted.
|
||||
*/
|
||||
function getDiffRanges(
|
||||
fileDiff: FileDiff,
|
||||
logger: Logger,
|
||||
79
src/languages/changes.test.ts
Normal file
79
src/languages/changes.test.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import test from "ava";
|
||||
|
||||
import type { FileDiff } from "../diff-informed";
|
||||
import { setupTests } from "../testing-utils";
|
||||
|
||||
import { matchPatterns, relevantChangeFor } from "./changes";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
function mkTestDiff(filename: string): FileDiff {
|
||||
return { filename, changes: 42 };
|
||||
}
|
||||
|
||||
test("matchPatterns - true if any pattern matches", (t) => {
|
||||
t.true(matchPatterns("/path/to/file.js", ["*.js"]));
|
||||
t.true(matchPatterns("/path/to", ["/path/**"]));
|
||||
t.true(matchPatterns("/path/to", ["foo.txt", "/path/**"]));
|
||||
t.true(matchPatterns("/path/to", ["foo.txt", "/path/from", "/path/to*"]));
|
||||
});
|
||||
|
||||
test("matchPatterns - false if no pattern matches", (t) => {
|
||||
t.false(matchPatterns("/path/to", []));
|
||||
t.false(matchPatterns("/path/to", ["/some/path/**"]));
|
||||
});
|
||||
|
||||
test("relevantChangeFor - relevant if expected", (t) => {
|
||||
// No configuration: all files are relevant
|
||||
t.true(relevantChangeFor({}, mkTestDiff("/path/to/file.js")));
|
||||
|
||||
// Various configurations that we expect to match the given path.
|
||||
t.true(
|
||||
relevantChangeFor({ patterns: ["*.js"] }, mkTestDiff("/path/to/file.js")),
|
||||
);
|
||||
t.true(
|
||||
relevantChangeFor(
|
||||
{ patterns: ["/path/**"] },
|
||||
mkTestDiff("/path/to/file.js"),
|
||||
),
|
||||
);
|
||||
|
||||
// `exclude` configuration doesn't apply
|
||||
t.true(
|
||||
relevantChangeFor({ exclude: ["*.ts"] }, mkTestDiff("/path/to/file.js")),
|
||||
);
|
||||
t.true(
|
||||
relevantChangeFor(
|
||||
{ patterns: ["*.js"], exclude: ["file.ts"] },
|
||||
mkTestDiff("/path/to/file.js"),
|
||||
),
|
||||
);
|
||||
t.true(
|
||||
relevantChangeFor(
|
||||
{ patterns: ["/path/**"], exclude: ["/path/to/**/*.ts"] },
|
||||
mkTestDiff("/path/to/file.js"),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test("relevantChangeFor - exclude patterns filter results", (t) => {
|
||||
// No patterns: all files are relevant, but `exclude` filters `.js` files.
|
||||
t.false(
|
||||
relevantChangeFor({ exclude: ["*.js"] }, mkTestDiff("/path/to/file.js")),
|
||||
);
|
||||
|
||||
// Various `patterns` configurations that we expect to match the given path and
|
||||
// more specific `exclude` configurations that we expect to also match.
|
||||
t.false(
|
||||
relevantChangeFor(
|
||||
{ patterns: ["*.js"], exclude: ["file.js"] },
|
||||
mkTestDiff("/path/to/file.js"),
|
||||
),
|
||||
);
|
||||
t.false(
|
||||
relevantChangeFor(
|
||||
{ patterns: ["/path/**"], exclude: ["/path/to/**/*.js"] },
|
||||
mkTestDiff("/path/to/file.js"),
|
||||
),
|
||||
);
|
||||
});
|
||||
112
src/languages/changes.ts
Normal file
112
src/languages/changes.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { minimatch } from "minimatch";
|
||||
|
||||
import type { FileDiff } from "../diff-informed";
|
||||
|
||||
import { BuiltInLanguage } from ".";
|
||||
|
||||
/**
|
||||
* Represents configurations for how to detect whether changes relate to a given analysis.
|
||||
*/
|
||||
export type ChangePatterns = {
|
||||
/**
|
||||
* A list of glob patterns.
|
||||
*
|
||||
* If a changed file has matches one of these, we conclude that files relevant to the
|
||||
* analysis have changed.
|
||||
*
|
||||
* If undefined, all changes are considered relevant.
|
||||
*/
|
||||
patterns?: string[];
|
||||
|
||||
/**
|
||||
* A list of glob patterns to exclude from `patterns`. Allows specific patterns to be excluded
|
||||
* that would otherwise be included by `patterns`.
|
||||
*
|
||||
* If a changed file matches one of `patterns` and `exclude`, then it is not considered
|
||||
* relevant to the analysis.
|
||||
*/
|
||||
exclude?: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* A mapping from all {@link BuildInLanguage}s to a {@link ChangePatterns} configuration.
|
||||
*/
|
||||
export const CHANGE_PATTERNS: Record<BuiltInLanguage, ChangePatterns> = {
|
||||
[BuiltInLanguage.actions]: {},
|
||||
[BuiltInLanguage.cpp]: {},
|
||||
[BuiltInLanguage.csharp]: {},
|
||||
[BuiltInLanguage.go]: {},
|
||||
[BuiltInLanguage.java]: {},
|
||||
[BuiltInLanguage.javascript]: {},
|
||||
[BuiltInLanguage.python]: {},
|
||||
[BuiltInLanguage.ruby]: {},
|
||||
[BuiltInLanguage.rust]: {},
|
||||
[BuiltInLanguage.swift]: {},
|
||||
};
|
||||
|
||||
/**
|
||||
* Decides whether {@link val} matches any of {@link patterns}. Returns early
|
||||
* as soon as a pattern matches.
|
||||
*/
|
||||
export function matchPatterns(val: string, patterns: string[]): boolean {
|
||||
for (const pattern of patterns) {
|
||||
if (minimatch(val, pattern, { matchBase: true })) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides whether {@link diff} matches the configuration in {@link changePatterns}.
|
||||
*
|
||||
* @param changePatterns The configuration of patterns to match {@link diff}'s path against.
|
||||
* @param diff A description of a change.
|
||||
*/
|
||||
export function relevantChangeFor(
|
||||
changePatterns: ChangePatterns,
|
||||
diff: FileDiff,
|
||||
): boolean {
|
||||
// If `patterns` is defined and none match, then the change is not relevant.
|
||||
if (
|
||||
changePatterns.patterns !== undefined &&
|
||||
!matchPatterns(diff.filename, changePatterns.patterns)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// At this point we have decided that the change is relevant, either because no
|
||||
// patterns are configured (all changes are relevant) or because one of the configured
|
||||
// patterns matched. Let's check if `exclude` patterns are configured and if any match.
|
||||
// If so, then we don't consider the change relevant after all.
|
||||
if (
|
||||
changePatterns.exclude !== undefined &&
|
||||
matchPatterns(diff.filename, changePatterns.exclude)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The change is relevant and none of the `exclude` patterns matched (or none were configured).
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides whether at least one of the given {@link diffs} matches the configuration for {@link language}
|
||||
* from {@link CHANGE_PATTERNS}.
|
||||
*
|
||||
* @param language The language to check for changes for.
|
||||
* @param diffs All changes to check.
|
||||
*/
|
||||
export function relevantChangesFor(
|
||||
language: BuiltInLanguage,
|
||||
diffs: FileDiff[],
|
||||
): boolean {
|
||||
for (const diff of diffs) {
|
||||
if (relevantChangeFor(CHANGE_PATTERNS[language], diff)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import test from "ava";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import * as actionsUtil from "../actions-util";
|
||||
import * as diffInformed from "../diff-informed";
|
||||
import * as gitUtils from "../git-utils";
|
||||
import {
|
||||
createTestConfig,
|
||||
@@ -60,7 +61,7 @@ test.serial(
|
||||
const diffRangeFilePath = path.join(tempDir, "pr-diff-range.json");
|
||||
sinon.stub(actionsUtil, "getTemporaryDirectory").returns(tempDir);
|
||||
sinon
|
||||
.stub(actionsUtil, "getDiffRangesJsonFilePath")
|
||||
.stub(diffInformed, "getDiffRangesJsonFilePath")
|
||||
.returns(diffRangeFilePath);
|
||||
sinon.stub(gitUtils, "getGitRoot").resolves(sourceRoot);
|
||||
const changesFilePath = await writeOverlayChangesFile(
|
||||
@@ -126,7 +127,7 @@ test.serial(
|
||||
const diffRangeFilePath = path.join(tempDir, "pr-diff-range.json");
|
||||
sinon.stub(actionsUtil, "getTemporaryDirectory").returns(tempDir);
|
||||
sinon
|
||||
.stub(actionsUtil, "getDiffRangesJsonFilePath")
|
||||
.stub(diffInformed, "getDiffRangesJsonFilePath")
|
||||
.returns(diffRangeFilePath);
|
||||
sinon.stub(gitUtils, "getGitRoot").resolves(sourceRoot);
|
||||
|
||||
@@ -196,7 +197,7 @@ test.serial(
|
||||
const diffRangeFilePath = path.join(tempDir, "pr-diff-range.json");
|
||||
sinon.stub(actionsUtil, "getTemporaryDirectory").returns(tempDir);
|
||||
sinon
|
||||
.stub(actionsUtil, "getDiffRangesJsonFilePath")
|
||||
.stub(diffInformed, "getDiffRangesJsonFilePath")
|
||||
.returns(diffRangeFilePath);
|
||||
sinon.stub(gitUtils, "getGitRoot").resolves(sourceRoot);
|
||||
|
||||
@@ -259,7 +260,7 @@ test.serial(
|
||||
const diffRangeFilePath = path.join(tempDir, "pr-diff-range.json");
|
||||
sinon.stub(actionsUtil, "getTemporaryDirectory").returns(tempDir);
|
||||
sinon
|
||||
.stub(actionsUtil, "getDiffRangesJsonFilePath")
|
||||
.stub(diffInformed, "getDiffRangesJsonFilePath")
|
||||
.returns(diffRangeFilePath);
|
||||
// getGitRoot returns the repo root (parent of sourceRoot)
|
||||
sinon.stub(gitUtils, "getGitRoot").resolves(repoRoot);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
import * as actionsUtil from "../actions-util";
|
||||
import { getOptionalInput, getTemporaryDirectory } from "../actions-util";
|
||||
import { type Config } from "../config-utils";
|
||||
import { getDiffRangesJsonFilePath } from "../diff-informed";
|
||||
import { getFileOidsUnderPath, getGitRoot } from "../git-utils";
|
||||
import { Logger } from "../logging";
|
||||
import { getBaseDatabaseOidsFilePath } from "../util";
|
||||
@@ -135,7 +135,7 @@ async function getDiffRangeFilePaths(
|
||||
sourceRoot: string,
|
||||
logger: Logger,
|
||||
): Promise<string[]> {
|
||||
const jsonFilePath = actionsUtil.getDiffRangesJsonFilePath();
|
||||
const jsonFilePath = getDiffRangesJsonFilePath();
|
||||
|
||||
if (!fs.existsSync(jsonFilePath)) {
|
||||
logger.debug(
|
||||
|
||||
@@ -1821,8 +1821,7 @@ function createToolcacheEntry(
|
||||
/**
|
||||
* Stubs out the download and the diagnostic sink, then downloads the CodeQL tools.
|
||||
*
|
||||
* @returns the extraction directory and, if the toolcache cleanup diagnostic was emitted, the
|
||||
* cleanup duration it reports and its other attributes.
|
||||
* @returns the extraction directory and the toolcache cleanup diagnostic, if emitted.
|
||||
*/
|
||||
async function runDownloadCodeQL(
|
||||
toolcacheRoot: string,
|
||||
@@ -1838,7 +1837,6 @@ async function runDownloadCodeQL(
|
||||
): Promise<{
|
||||
codeqlFolder: string;
|
||||
cleanupDiagnostic: toolsDownload.ToolcacheCleanupResult | undefined;
|
||||
cleanupDurationMs: number | undefined;
|
||||
}> {
|
||||
stubDownloadAndExtract();
|
||||
const addDiagnostic = sinon.stub(diagnostics, "addNoLanguageDiagnostic");
|
||||
@@ -1868,21 +1866,11 @@ async function runDownloadCodeQL(
|
||||
.map((call) => call.args[1])
|
||||
.find((d) => d.source?.id === "codeql-action/toolcache-bundle-cleanup");
|
||||
|
||||
if (diagnostic === undefined) {
|
||||
return {
|
||||
codeqlFolder,
|
||||
cleanupDiagnostic: undefined,
|
||||
cleanupDurationMs: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
// The duration varies between runs, so split it out to let tests compare the other attributes
|
||||
// exactly.
|
||||
const { durationMs, ...cleanupDiagnostic } =
|
||||
diagnostic.attributes as toolsDownload.ToolcacheCleanupResult & {
|
||||
durationMs: number;
|
||||
};
|
||||
return { codeqlFolder, cleanupDiagnostic, cleanupDurationMs: durationMs };
|
||||
return {
|
||||
codeqlFolder,
|
||||
cleanupDiagnostic: diagnostic?.attributes as
|
||||
toolsDownload.ToolcacheCleanupResult | undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2003,35 +1991,6 @@ test.serial(
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"downloadCodeQLBundle reports the total time taken to clean up the toolcache",
|
||||
async (t) => {
|
||||
await withTmpDir(async (tmpDir) => {
|
||||
setupActionsVars(tmpDir, tmpDir);
|
||||
|
||||
createToolcacheEntry(tmpDir, "CodeQL", CLEANUP_CLI_VERSION);
|
||||
createToolcacheEntry(tmpDir, "CodeQL", CLEANUP_STALE_VERSION);
|
||||
|
||||
// Advance the clock by 1.5s each time a path is deleted, so that deleting both versions
|
||||
// takes 3s.
|
||||
let elapsedMs = 1000;
|
||||
sinon.stub(performance, "now").callsFake(() => elapsedMs);
|
||||
const rm = fs.promises.rm;
|
||||
sinon.stub(fs.promises, "rm").callsFake(async (...args) => {
|
||||
elapsedMs += 1500;
|
||||
await rm(...args);
|
||||
});
|
||||
|
||||
const { cleanupDurationMs } = await runDownloadCodeQL(
|
||||
tmpDir,
|
||||
CLEANUP_BUNDLE_VERSION,
|
||||
);
|
||||
|
||||
t.is(cleanupDurationMs, 3000);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.serial(
|
||||
"downloadCodeQLBundle reports no deleted versions when the toolcache has no CodeQL bundles",
|
||||
async (t) => {
|
||||
|
||||
@@ -814,7 +814,6 @@ async function tryDeleteToolcacheBundles({
|
||||
return;
|
||||
}
|
||||
|
||||
const startTime = performance.now();
|
||||
const result = await deleteToolcacheBundles({ env, logger });
|
||||
|
||||
addNoLanguageDiagnostic(
|
||||
@@ -822,7 +821,7 @@ async function tryDeleteToolcacheBundles({
|
||||
makeTelemetryDiagnostic(
|
||||
"codeql-action/toolcache-bundle-cleanup",
|
||||
"Toolcache CodeQL bundle cleanup",
|
||||
{ ...result, durationMs: util.durationMsSince(startTime) },
|
||||
{ ...result },
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -342,16 +342,13 @@ export async function deleteToolcacheBundles({
|
||||
const versionDirectory = path.join(toolDirectory, entry.name);
|
||||
|
||||
try {
|
||||
const deletionStart = performance.now();
|
||||
await fs.promises.rm(versionDirectory, {
|
||||
force: true,
|
||||
recursive: true,
|
||||
});
|
||||
deletedVersions.push(entry.name);
|
||||
logger.info(
|
||||
`Deleted the CodeQL tools at '${versionDirectory}' from the toolcache to free up disk space (${formatDuration(
|
||||
durationMsSince(deletionStart),
|
||||
)}).`,
|
||||
`Deleted the CodeQL tools at '${versionDirectory}' from the toolcache to free up disk space.`,
|
||||
);
|
||||
} catch (e) {
|
||||
failed = true;
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as sinon from "sinon";
|
||||
import * as analyses from "./analyses";
|
||||
import { AnalysisKind, CodeQuality, CodeScanning } from "./analyses";
|
||||
import * as api from "./api-client";
|
||||
import * as diffUtils from "./diff-informed-analysis-utils";
|
||||
import * as diffUtils from "./diff-informed";
|
||||
import { getEnv } from "./environment";
|
||||
import { Logger } from "./logging";
|
||||
import * as sarif from "./sarif";
|
||||
@@ -1074,6 +1074,7 @@ function runFilterAlertsByDiffRange(
|
||||
logger: Logger = new RecordingLogger(),
|
||||
): Partial<sarif.Log> {
|
||||
sinon.stub(diffUtils, "readDiffRangesJsonFile").returns(diffRanges);
|
||||
sinon.stub(diffUtils, "getDiffRangesJsonFilePath").returns("");
|
||||
return uploadLib.filterAlertsByDiffRange(logger, input);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,10 @@ import * as api from "./api-client";
|
||||
import { getGitHubVersion, wrapApiConfigurationError } from "./api-client";
|
||||
import { CodeQL, getCodeQL } from "./codeql";
|
||||
import type { ActionConfig } from "./config/action-config";
|
||||
import { readDiffRangesJsonFile } from "./diff-informed-analysis-utils";
|
||||
import {
|
||||
getDiffRangesJsonFilePath,
|
||||
readDiffRangesJsonFile,
|
||||
} from "./diff-informed";
|
||||
import { ActionsEnvVars, EnvVar, exportEnvVar } from "./environment";
|
||||
import { FeatureEnablement } from "./feature-flags";
|
||||
import * as fingerprints from "./fingerprints";
|
||||
@@ -1079,7 +1082,10 @@ export function filterAlertsByDiffRange(
|
||||
logger: Logger,
|
||||
sarifLog: Partial<sarif.Log>,
|
||||
): Partial<sarif.Log> {
|
||||
const diffRanges = readDiffRangesJsonFile(logger);
|
||||
const diffRanges = readDiffRangesJsonFile(
|
||||
logger,
|
||||
getDiffRangesJsonFilePath(),
|
||||
);
|
||||
if (!diffRanges?.length) {
|
||||
return sarifLog;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
- Fixed diff-informed alert filtering incorrectly removing alerts in changed files whose paths contain spaces, special characters, or non-ASCII characters. [#4283](https://github.com/github/codeql-action/pull/4283)
|
||||
Reference in New Issue
Block a user