From d1d68a07a7974175bcb688b1f2505769fabaca64 Mon Sep 17 00:00:00 2001 From: komal mahale Date: Fri, 29 May 2026 12:06:50 +0530 Subject: [PATCH 1/4] feat: add CodeQL GitHub Actions workflow Run CodeQL via Bazel on all relevant C++ targets (//score/...) on every pull_request and push to main, then upload the resulting SARIF file to GitHub Code Scanning via github/codeql-action/upload-sarif. Without this upload step GitHub has no stored baseline, causing every PR to incorrectly report no new alerts introduced. Refs: https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github --- .github/workflows/codeql.yml | 89 ++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..60a07c423 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,89 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +# Workflow: CodeQL analysis on push to main and on demand. +# +# Runs CodeQL via Bazel on all relevant C++ targets under //score/... +# and uploads the resulting SARIF file to GitHub Code Scanning so that: +# - GitHub tracks findings over time with a stable baseline on main. +# - New PRs are compared against that baseline to surface new findings. +# +# Why not run on pull_request? +# The full CodeQL analysis (169 MISRA rules over //score/...) exceeds +# GitHub's 6-hour runner limit and is cancelled before producing output. +# Running on push to main ensures a complete, uploadable baseline exists. +# GitHub Code Scanning then uses that baseline to flag new findings per PR. +# +# Reference: https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github + +name: CodeQL Analysis + +on: + push: + branches: [main] + workflow_dispatch: # Allow maintainers to trigger manually when needed + +permissions: + contents: read + security-events: write # Required to upload SARIF results to GitHub Code Scanning + +concurrency: + group: codeql-${{ github.run_id }} + cancel-in-progress: false # Never cancel an in-progress CodeQL run; it takes hours + +env: + ANDROID_HOME: "" + ANDROID_SDK_ROOT: "" + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + codeql: + runs-on: ubuntu-24.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Free Disk Space (Ubuntu) + uses: eclipse-score/more-disk-space@v1 + with: + level: 4 + + - name: Setup Bazel + uses: castler/setup-bazel@cache-optimized + with: + bazelisk-cache: true + disk-cache: "codeql" + repository-cache: true + cache-optimized: true + cache-save: ${{ github.ref == 'refs/heads/main' }} + + - name: Allow linux-sandbox + uses: ./actions/unblock_user_namespace_for_linux_sandbox + + - name: Run CodeQL via Bazel + run: | + bazel run //quality/static_analysis:codeql_lint -- \ + --target //score/... + + - name: Locate SARIF output + id: sarif + run: | + SARIF_PATH="$(bazel info output_path)/codeql.sarif" + echo "path=${SARIF_PATH}" >> "$GITHUB_OUTPUT" + + - name: Upload SARIF to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: ${{ steps.sarif.outputs.path }} + category: codeql-bazel From 10a79ada5ad4ad839a3c3226c8be1a3955fce7bf Mon Sep 17 00:00:00 2001 From: komal mahale Date: Fri, 29 May 2026 12:06:50 +0530 Subject: [PATCH 2/4] feat: add CodeQL GitHub Actions workflow Run CodeQL via Bazel on all relevant C++ targets (//score/...) on every pull_request and push to main, then upload the resulting SARIF file to GitHub Code Scanning via github/codeql-action/upload-sarif. Without this upload step GitHub has no stored baseline, causing every PR to incorrectly report no new alerts introduced. Refs: https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github --- .github/workflows/codeql.yml | 89 ++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..60a07c423 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,89 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +# Workflow: CodeQL analysis on push to main and on demand. +# +# Runs CodeQL via Bazel on all relevant C++ targets under //score/... +# and uploads the resulting SARIF file to GitHub Code Scanning so that: +# - GitHub tracks findings over time with a stable baseline on main. +# - New PRs are compared against that baseline to surface new findings. +# +# Why not run on pull_request? +# The full CodeQL analysis (169 MISRA rules over //score/...) exceeds +# GitHub's 6-hour runner limit and is cancelled before producing output. +# Running on push to main ensures a complete, uploadable baseline exists. +# GitHub Code Scanning then uses that baseline to flag new findings per PR. +# +# Reference: https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github + +name: CodeQL Analysis + +on: + push: + branches: [main] + workflow_dispatch: # Allow maintainers to trigger manually when needed + +permissions: + contents: read + security-events: write # Required to upload SARIF results to GitHub Code Scanning + +concurrency: + group: codeql-${{ github.run_id }} + cancel-in-progress: false # Never cancel an in-progress CodeQL run; it takes hours + +env: + ANDROID_HOME: "" + ANDROID_SDK_ROOT: "" + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + codeql: + runs-on: ubuntu-24.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Free Disk Space (Ubuntu) + uses: eclipse-score/more-disk-space@v1 + with: + level: 4 + + - name: Setup Bazel + uses: castler/setup-bazel@cache-optimized + with: + bazelisk-cache: true + disk-cache: "codeql" + repository-cache: true + cache-optimized: true + cache-save: ${{ github.ref == 'refs/heads/main' }} + + - name: Allow linux-sandbox + uses: ./actions/unblock_user_namespace_for_linux_sandbox + + - name: Run CodeQL via Bazel + run: | + bazel run //quality/static_analysis:codeql_lint -- \ + --target //score/... + + - name: Locate SARIF output + id: sarif + run: | + SARIF_PATH="$(bazel info output_path)/codeql.sarif" + echo "path=${SARIF_PATH}" >> "$GITHUB_OUTPUT" + + - name: Upload SARIF to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: ${{ steps.sarif.outputs.path }} + category: codeql-bazel From 030cb7469650f5d08fa0796a0a9e71cf0de14e55 Mon Sep 17 00:00:00 2001 From: komal mahale Date: Mon, 1 Jun 2026 15:37:15 +0530 Subject: [PATCH 3/4] ci: run CodeQL on PR, main, and merge queue --- .github/workflows/codeql.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 60a07c423..f112141ad 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -11,26 +11,26 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -# Workflow: CodeQL analysis on push to main and on demand. +# Workflow: CodeQL analysis on pull_request, push to main, merge_group, and on demand. # # Runs CodeQL via Bazel on all relevant C++ targets under //score/... # and uploads the resulting SARIF file to GitHub Code Scanning so that: +# - CodeQL is executed on every PR (acceptance criteria). # - GitHub tracks findings over time with a stable baseline on main. # - New PRs are compared against that baseline to surface new findings. -# -# Why not run on pull_request? -# The full CodeQL analysis (169 MISRA rules over //score/...) exceeds -# GitHub's 6-hour runner limit and is cancelled before producing output. -# Running on push to main ensures a complete, uploadable baseline exists. -# GitHub Code Scanning then uses that baseline to flag new findings per PR. +# - Gate (merge_group) runs use the same scope as PR runs for consistency. # # Reference: https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github name: CodeQL Analysis on: + pull_request: + types: [opened, reopened, synchronize] push: branches: [main] + merge_group: + types: [checks_requested] workflow_dispatch: # Allow maintainers to trigger manually when needed permissions: @@ -49,6 +49,7 @@ env: jobs: codeql: runs-on: ubuntu-24.04 + timeout-minutes: 340 # CodeQL full scan is long; cap below GitHub's 6-hour hard limit steps: - name: Checkout repository From b73340785560f24058a34acff3ec5fd4eca2a13f Mon Sep 17 00:00:00 2001 From: komal mahale Date: Mon, 1 Jun 2026 16:09:46 +0530 Subject: [PATCH 4/4] ci: smart-pick CodeQL targets for PR runs --- .github/workflows/codeql.yml | 93 ++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f112141ad..dbc72d081 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -13,12 +13,12 @@ # Workflow: CodeQL analysis on pull_request, push to main, merge_group, and on demand. # -# Runs CodeQL via Bazel on all relevant C++ targets under //score/... -# and uploads the resulting SARIF file to GitHub Code Scanning so that: +# Runs CodeQL via Bazel on relevant C++ targets under //score/... and uploads +# the resulting SARIF file to GitHub Code Scanning so that: # - CodeQL is executed on every PR (acceptance criteria). +# - PR and merge_group runs use a smart target-picker based on changed files. +# - Pushes to main and manual runs always scan full //score/... for baseline. # - GitHub tracks findings over time with a stable baseline on main. -# - New PRs are compared against that baseline to surface new findings. -# - Gate (merge_group) runs use the same scope as PR runs for consistency. # # Reference: https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github @@ -72,18 +72,101 @@ jobs: - name: Allow linux-sandbox uses: ./actions/unblock_user_namespace_for_linux_sandbox + - name: Pick CodeQL targets + id: targets + run: | + set -euo pipefail + + DEFAULT_TARGET="//score/..." + EVENT_NAME="${GITHUB_EVENT_NAME}" + TARGET="${DEFAULT_TARGET}" + REASON="main_or_manual_full_scan" + + if [[ "${EVENT_NAME}" == "pull_request" || "${EVENT_NAME}" == "merge_group" ]]; then + BASE_BRANCH="${GITHUB_BASE_REF:-main}" + git fetch --no-tags --depth=1 origin "${BASE_BRANCH}" + + CHANGED_FILES="$(git diff --name-only "origin/${BASE_BRANCH}...HEAD" || true)" + + if [[ -z "${CHANGED_FILES}" ]]; then + TARGET="${DEFAULT_TARGET}" + REASON="no_changes_detected_fallback_full_scan" + elif echo "${CHANGED_FILES}" | grep -Eq '^(WORKSPACE|MODULE\.bazel|BUILD|\.bazelrc|bazel/|quality/static_analysis/|third_party/|tools/|\.github/workflows/codeql\.yml)'; then + TARGET="${DEFAULT_TARGET}" + REASON="infra_or_tooling_change_full_scan" + else + mapfile -t SCORE_FILES < <(echo "${CHANGED_FILES}" | grep -E '^score/.*' || true) + + if [[ "${#SCORE_FILES[@]}" -eq 0 ]]; then + TARGET="" + REASON="no_score_changes_skip_scan" + else + : > affected_targets.txt + + for file_path in "${SCORE_FILES[@]}"; do + label="//$(dirname "${file_path}"):$(basename "${file_path}")" + bazel query "kind('.* rule', rdeps(//score/..., ${label}))" 2>/dev/null >> affected_targets.txt || true + done + + sort -u affected_targets.txt -o affected_targets.txt + + if [[ ! -s affected_targets.txt ]]; then + TARGET="${DEFAULT_TARGET}" + REASON="empty_query_result_fallback_full_scan" + else + TARGET_COUNT="$(wc -l < affected_targets.txt | tr -d ' ')" + if [[ "${TARGET_COUNT}" -gt 300 ]]; then + TARGET="${DEFAULT_TARGET}" + REASON="too_many_targets_fallback_full_scan" + else + TARGET="$(tr '\n' ' ' < affected_targets.txt | sed 's/[[:space:]]*$//')" + REASON="smart_target_picker" + fi + fi + fi + fi + fi + + echo "target=${TARGET}" >> "$GITHUB_OUTPUT" + echo "reason=${REASON}" >> "$GITHUB_OUTPUT" + + { + echo "## CodeQL Target Selection" + echo "" + echo "| Field | Value |" + echo "|---|---|" + echo "| Event | ${EVENT_NAME} |" + echo "| Reason | ${REASON} |" + + if [[ -z "${TARGET}" ]]; then + echo "| Targets | _none_ (skipped: no score/ changes) |" + elif [[ "${TARGET}" == "${DEFAULT_TARGET}" ]]; then + echo "| Targets | ${DEFAULT_TARGET} |" + else + echo "| Targets | smart-picked subset |" + echo "" + echo "### Picked Targets" + echo '```' + cat affected_targets.txt + echo '```' + fi + } >> "$GITHUB_STEP_SUMMARY" + - name: Run CodeQL via Bazel + if: ${{ steps.targets.outputs.target != '' }} run: | bazel run //quality/static_analysis:codeql_lint -- \ - --target //score/... + --target "${{ steps.targets.outputs.target }}" - name: Locate SARIF output id: sarif + if: ${{ steps.targets.outputs.target != '' }} run: | SARIF_PATH="$(bazel info output_path)/codeql.sarif" echo "path=${SARIF_PATH}" >> "$GITHUB_OUTPUT" - name: Upload SARIF to GitHub Code Scanning + if: ${{ steps.targets.outputs.target != '' }} uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ steps.sarif.outputs.path }}