diff --git a/.github/scripts/codeql-matrix.sh b/.github/scripts/codeql-matrix.sh
new file mode 100644
index 00000000..1da56115
--- /dev/null
+++ b/.github/scripts/codeql-matrix.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+set -euo pipefail
+
+java_build_mode="${1:-autobuild}"
+
+matrix_entries=""
+
+has_files() {
+ git ls-files "$@" | grep . >/dev/null
+}
+
+add_entry() {
+ local entry="$1"
+ if [ -n "$matrix_entries" ]; then
+ matrix_entries="$matrix_entries,$entry"
+ else
+ matrix_entries="$entry"
+ fi
+}
+
+if has_files '.github/workflows/*.yml' '.github/workflows/*.yaml'; then
+ add_entry '{"language":"actions","build-mode":"none"}'
+fi
+
+if has_files '*.java'; then
+ add_entry "{\"language\":\"java-kotlin\",\"build-mode\":\"$java_build_mode\"}"
+fi
+
+if has_files '*.js' '*.jsx' '*.ts' '*.tsx' '*.mjs' '*.cjs' '*.vue' '*.html'; then
+ add_entry '{"language":"javascript-typescript","build-mode":"none"}'
+fi
+
+printf '{"include":[%s]}\n' "$matrix_entries"
diff --git a/.github/workflows/codeql-full.yml b/.github/workflows/codeql-full.yml
new file mode 100644
index 00000000..aeeece0b
--- /dev/null
+++ b/.github/workflows/codeql-full.yml
@@ -0,0 +1,221 @@
+name: CodeQL Full Scan
+
+on:
+ schedule:
+ - cron: '34 7 * * 1'
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ security-events: write
+ packages: read
+ actions: read
+
+jobs:
+ detect:
+ name: Detect CodeQL languages
+ runs-on: ubuntu-latest
+ env:
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
+ outputs:
+ matrix: ${{ steps.matrix.outputs.matrix }}
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+
+ - name: Build matrix
+ id: matrix
+ shell: bash
+ run: |
+ matrix=$(bash .github/scripts/codeql-matrix.sh manual)
+ printf 'matrix=%s\n' "$matrix" >> "$GITHUB_OUTPUT"
+
+ analyze:
+ needs: detect
+ name: Full scan (${{ matrix.language }})
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix: ${{ fromJSON(needs.detect.outputs.matrix) }}
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+
+ - name: Set up JDK 17
+ if: matrix.language == 'java-kotlin'
+ uses: actions/setup-java@v5
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v4
+ with:
+ languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
+
+ - name: Build project
+ if: matrix.language == 'java-kotlin'
+ run: mvn -B clean test-compile -DskipTests -Dcheckstyle.skip=true -Dpmd.skip=true -Dspotbugs.skip=true -Dcpd.skip=true
+
+ - name: Prepare CodeQL SARIF directory
+ shell: bash
+ run: |
+ rm -rf codeql-sarif
+ mkdir -p codeql-sarif
+
+ - name: Perform CodeQL Analysis
+ id: codeql-analysis
+ uses: github/codeql-action/analyze@v4
+ with:
+ output: ${{ github.workspace }}/codeql-sarif
+ upload: always
+ category: "/codeql-full:${{ matrix.language }}"
+
+ - name: Summarize CodeQL SARIF report
+ id: sarif-summary
+ if: always()
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ mkdir -p codeql-sarif
+ report_index="codeql-sarif/scan-files.txt"
+ sarif_count=0
+ invalid_sarif=0
+ violations=0
+
+ {
+ printf 'language=%s\n' '${{ matrix.language }}'
+ printf 'codeql_output=%s\n' '${{ github.workspace }}/codeql-sarif'
+ printf '\nGenerated SARIF files:\n'
+ } > "$report_index"
+
+ while IFS= read -r -d '' file; do
+ sarif_count=$((sarif_count + 1))
+ result_count=$(jq '[.runs[]?.results[]?] | length' "$file" 2>/dev/null || true)
+
+ if [[ "$result_count" =~ ^[0-9]+$ ]]; then
+ violations=$((violations + result_count))
+ printf '%s results=%s\n' "$file" "$result_count" >> "$report_index"
+ else
+ invalid_sarif=$((invalid_sarif + 1))
+ printf '%s results=invalid-sarif\n' "$file" >> "$report_index"
+ fi
+ done < <(find codeql-sarif -type f -name '*.sarif' -print0)
+
+ {
+ printf '\nSummary:\n'
+ printf 'sarif_count=%s\n' "$sarif_count"
+ printf 'invalid_sarif=%s\n' "$invalid_sarif"
+ printf 'violations=%s\n' "$violations"
+ } >> "$report_index"
+
+ printf 'sarif_count=%s\n' "$sarif_count" >> "$GITHUB_OUTPUT"
+ printf 'invalid_sarif=%s\n' "$invalid_sarif" >> "$GITHUB_OUTPUT"
+ printf 'violations=%s\n' "$violations" >> "$GITHUB_OUTPUT"
+
+ - name: Install SARIF tools
+ if: ${{ always() && hashFiles('codeql-sarif/**/*.sarif') != '' }}
+ run: python -m pip install sarif-tools
+
+ - name: Generate CodeQL HTML report
+ id: html-report
+ if: ${{ always() && hashFiles('codeql-sarif/**/*.sarif') != '' }}
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ html_dir="codeql-html-report"
+ rm -rf "$html_dir"
+ mkdir -p "$html_dir"
+
+ html_count=0
+ while IFS= read -r -d '' sarif_file; do
+ sarif html "$sarif_file" --output "$html_dir"
+ html_count=$((html_count + 1))
+ printf '%s -> %s/\n' "$sarif_file" "$html_dir"
+ done < <(find codeql-sarif -type f -name '*.sarif' -print0)
+
+ index_file="$html_dir/reports.html"
+ {
+ printf '\n'
+ printf '\n'
+ printf '
CodeQL HTML Reports\n'
+ printf '\n'
+ printf 'CodeQL HTML Reports - %s
\n' '${{ matrix.language }}'
+ printf '\n'
+ while IFS= read -r -d '' html_file; do
+ link="${html_file#$html_dir/}"
+ printf '- %s
\n' "$link" "$link"
+ done < <(find "$html_dir" -maxdepth 1 -type f -name '*.html' ! -name 'reports.html' -print0 | sort -z)
+ printf '
\n'
+ printf '\n'
+ printf '\n'
+ } > "$index_file"
+
+ if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
+ {
+ printf '## CodeQL HTML report\n\n'
+ printf '| Metric | Result |\n'
+ printf '|------|------|\n'
+ printf '| Language | %s |\n' '${{ matrix.language }}'
+ printf '| HTML files | %s |\n' "$html_count"
+ printf '| Artifact | codeql-full-html-%s |\n' '${{ matrix.language }}'
+ } >> "$GITHUB_STEP_SUMMARY"
+ fi
+
+ printf 'html_count=%s\n' "$html_count" >> "$GITHUB_OUTPUT"
+
+ - name: Upload CodeQL SARIF report
+ if: always()
+ uses: actions/upload-artifact@v7
+ with:
+ name: codeql-full-sarif-${{ matrix.language }}
+ path: codeql-sarif
+ if-no-files-found: error
+ retention-days: 30
+
+ - name: Upload CodeQL HTML report
+ if: ${{ always() && hashFiles('codeql-html-report/**/*.html') != '' }}
+ uses: actions/upload-artifact@v7
+ with:
+ name: codeql-full-html-${{ matrix.language }}
+ path: codeql-html-report
+ if-no-files-found: error
+ retention-days: 30
+
+ - name: Check CodeQL findings
+ if: always()
+ shell: bash
+ env:
+ SARIF_COUNT: ${{ steps.sarif-summary.outputs.sarif_count }}
+ INVALID_SARIF: ${{ steps.sarif-summary.outputs.invalid_sarif }}
+ VIOLATIONS: ${{ steps.sarif-summary.outputs.violations }}
+ run: |
+ sarif_count="${SARIF_COUNT:-0}"
+ invalid_sarif="${INVALID_SARIF:-0}"
+ violations="${VIOLATIONS:-0}"
+
+ if [[ "$sarif_count" -eq 0 ]]; then
+ echo "::error::CodeQL did not produce a SARIF report."
+ exit 1
+ fi
+
+ if [[ "$invalid_sarif" -ne 0 ]]; then
+ echo "::error::CodeQL produced $invalid_sarif invalid SARIF report(s)."
+ exit 1
+ fi
+
+ if [[ "$violations" -ne 0 ]]; then
+ echo "::error::CodeQL found $violations result(s)."
+ exit 1
+ fi
+
+ echo "CodeQL found no results."
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 1a5d4ced..d022f03d 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -1,102 +1,66 @@
-# For most projects, this workflow file will not need changing; you simply need
-# to commit it to your repository.
-#
-# You may wish to alter this file to override the set of languages analyzed,
-# or to provide custom queries or build logic.
-#
-# ******** NOTE ********
-# We have attempted to detect the languages in your repository. Please check
-# the `language` matrix defined below to confirm you have the correct set of
-# supported CodeQL languages.
-#
-name: "CodeQL Advanced"
+name: CodeQL Incremental
on:
push:
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]
- schedule:
- - cron: '24 15 * * 1'
-jobs:
- analyze:
- name: Analyze (${{ matrix.language }})
- # Runner size impacts CodeQL analysis time. To learn more, please see:
- # - https://gh.io/recommended-hardware-resources-for-running-codeql
- # - https://gh.io/supported-runners-and-hardware-resources
- # - https://gh.io/using-larger-runners (GitHub.com only)
- # Consider using larger runners or machines with greater resources for possible analysis time improvements.
- runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
- permissions:
- # required for all workflows
- security-events: write
+permissions:
+ contents: read
+ security-events: write
+ packages: read
+ actions: read
- # required to fetch internal or private CodeQL packs
- packages: read
+jobs:
+ detect:
+ name: Detect CodeQL languages
+ runs-on: ubuntu-latest
+ outputs:
+ matrix: ${{ steps.matrix.outputs.matrix }}
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- # only required for workflows in private repositories
- actions: read
- contents: read
+ - name: Build matrix
+ id: matrix
+ shell: bash
+ run: |
+ matrix=$(bash .github/scripts/codeql-matrix.sh autobuild)
+ printf 'matrix=%s\n' "$matrix" >> "$GITHUB_OUTPUT"
+ analyze:
+ needs: detect
+ name: Analyze (${{ matrix.language }})
+ runs-on: ubuntu-latest
strategy:
fail-fast: false
- matrix:
- include:
- - language: actions
- build-mode: none
- - language: java-kotlin
- build-mode: autobuild # This mode only analyzes Java. Set this to 'autobuild' or 'manual' to analyze Kotlin too.
- # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
- # Use `c-cpp` to analyze code written in C, C++ or both
- # Use 'java-kotlin' to analyze code written in Java, Kotlin or both
- # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
- # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
- # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
- # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
- # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
+ matrix: ${{ fromJSON(needs.detect.outputs.matrix) }}
- # Add any setup steps before running the `github/codeql-action/init` action.
- # This includes steps like installing compilers or runtimes (`actions/setup-node`
- # or others). This is typically only required for manual builds.
- # - name: Setup runtime (example)
- # uses: actions/setup-example@v1
-
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v4
- with:
- languages: ${{ matrix.language }}
- build-mode: ${{ matrix.build-mode }}
- config-file: ./.github/codeql/codeql-config.yml
- # If you wish to specify custom queries, you can do so here or in a config file.
- # By default, queries listed here will override any specified in a config file.
- # Prefix the list here with "+" to use these queries and those in the config file.
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
- # queries: security-extended,security-and-quality
+ - name: Set up JDK 17
+ if: matrix.language == 'java-kotlin'
+ uses: actions/setup-java@v5
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
- # If the analyze step fails for one of the languages you are analyzing with
- # "We were unable to automatically build your code", modify the matrix above
- # to set the build mode to "manual" for that language. Then modify this step
- # to build your code.
- # âšī¸ Command-line programs to run using the OS shell.
- # đ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- - name: Run manual build steps
- if: matrix.build-mode == 'manual'
- shell: bash
- run: |
- echo 'If you are using a "manual" build mode for one or more of the' \
- 'languages you are analyzing, replace this with the commands to build' \
- 'your code, for example:'
- echo ' make bootstrap'
- echo ' make release'
- exit 1
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v4
+ with:
+ languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
+ config-file: ./.github/codeql/codeql-config.yml
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v4
- with:
- category: "/language:${{matrix.language}}"
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v4
+ with:
+ category: "/language:${{ matrix.language }}"