From edcaf225cf502229ed8dfee81adfe4f91df933f7 Mon Sep 17 00:00:00 2001 From: Saumya Rai Date: Fri, 13 Mar 2026 13:31:10 +0530 Subject: [PATCH 1/2] Fix script to handle SARIF file recategorization adding GitPython lib cleaning the files for redundant made Codeql executable with bazel fixing bzel run issues adding a version removing timeout addresses several issues related to environment-specific paths and execution context removing the ref --- .github/codeql/codeql-config.yml | 8 + .../workflows/codeql-multiple-repo-scan.yml | 45 ++-- feature_integration_tests/test_cases/BUILD | 3 + .../test_cases/requirements.txt.lock | 68 ++---- scripts/tooling/BUILD | 33 ++- scripts/tooling/cli/workflow/__init__.py | 12 + .../tooling/cli/workflow/checkout_repos.py | 109 +++++++++ .../cli/workflow/recategorize_guidelines.py | 227 ++++++++++++++++++ scripts/tooling/lib/git_operations.py | 118 +++++++++ scripts/tooling/requirements.in | 1 + scripts/tooling/requirements.txt | 44 +--- scripts/workflow/checkout_repos.sh | 47 ---- scripts/workflow/parse_repos.sh | 54 ----- scripts/workflow/recategorize_guidelines.sh | 28 --- 14 files changed, 567 insertions(+), 230 deletions(-) create mode 100644 scripts/tooling/cli/workflow/__init__.py create mode 100755 scripts/tooling/cli/workflow/checkout_repos.py create mode 100755 scripts/tooling/cli/workflow/recategorize_guidelines.py create mode 100644 scripts/tooling/lib/git_operations.py delete mode 100755 scripts/workflow/checkout_repos.sh delete mode 100755 scripts/workflow/parse_repos.sh delete mode 100755 scripts/workflow/recategorize_guidelines.sh diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index 88d151e9ae3..06a756dec8b 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -19,3 +19,11 @@ paths-ignore: - "**/test/**" - "**/mock/**" - "**/codeql-coding-standards-repo/**" + - "**/examples/**" + - "**/docs/**" + - "**/target/**" + - "**/bazel-*/**" + - "**/.git/**" + - "**/node_modules/**" + - "**/build/**" + - "**/dist/**" diff --git a/.github/workflows/codeql-multiple-repo-scan.yml b/.github/workflows/codeql-multiple-repo-scan.yml index a22531153b2..6ec2ece8c66 100644 --- a/.github/workflows/codeql-multiple-repo-scan.yml +++ b/.github/workflows/codeql-multiple-repo-scan.yml @@ -32,6 +32,7 @@ jobs: analyze-repos: name: Analyze Multiple Repositories runs-on: ubuntu-latest + timeout-minutes: 120 # Prevent indefinite hanging permissions: security-events: write packages: read @@ -40,25 +41,23 @@ jobs: steps: - name: Checkout central repository uses: actions/checkout@v4 - - name: Checkout CodeQL Coding Standards scripts - uses: actions/checkout@v4 - with: - repository: github/codeql-coding-standards - path: codeql-coding-standards-repo # Klonen in diesen Ordner - ref: main # Oder eine spezifische Release-Version, z.B. 'v2.53.0-dev' - # Add coding standard packages and dependencies - - name: Install Python dependencies for Coding Standards scripts + - name: Install sarif-tools for HTML report generation run: | python3 -m pip install --upgrade pip - pip3 install pyyaml jsonpath-ng jsonschema jsonpatch jsonpointer pytest sarif-tools - - name: Parse known_good.json and create repos.json - id: parse-repos - run: | - scripts/workflow/parse_repos.sh + pip3 install sarif-tools + - name: Cache repository checkouts + uses: actions/cache@v4 + with: + path: repos/ + key: repos-${{ hashFiles('known_good.json') }} + restore-keys: | + repos- - name: Checkout all pinned repositories id: checkout-repos + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - scripts/workflow/checkout_repos.sh + bazel run //scripts/tooling:checkout_repos - name: Initialize CodeQL for all repositories uses: github/codeql-action/init@v4 with: @@ -69,16 +68,30 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 with: - upload-database: false # Don't upload databases for each repo + upload-database: false output: sarif-results/ category: "multi-repo-scan" + - name: Cleanup repository checkouts + if: always() + run: | + echo "Cleaning up checked out repositories to free disk space" + rm -rf repos/ + - name: Checkout CodeQL Coding Standards scripts + uses: actions/checkout@v4 + with: + repository: github/codeql-coding-standards + path: codeql-coding-standards-repo - name: Recategorize Guidelines if: always() run: | - scripts/workflow/recategorize_guidelines.sh + bazel run //scripts/tooling:recategorize_guidelines - name: Generate HTML Report from SARIF run: | SARIF_FILE="sarif-results/cpp.sarif" + if [ ! -f "$SARIF_FILE" ]; then + echo "Error: SARIF file not found at $SARIF_FILE" + exit 1 + fi sarif html "$SARIF_FILE" --output codeql-report.html - name: Upload SARIF results as artifact uses: actions/upload-artifact@v4 diff --git a/feature_integration_tests/test_cases/BUILD b/feature_integration_tests/test_cases/BUILD index 40cc724aa51..ab0717abf1d 100644 --- a/feature_integration_tests/test_cases/BUILD +++ b/feature_integration_tests/test_cases/BUILD @@ -25,6 +25,9 @@ compile_pip_requirements( "requirements.txt", "@score_tooling//python_basics:requirements.txt", ], + extra_args = [ + "--no-annotate", + ], requirements_txt = "requirements.txt.lock", tags = [ "manual", diff --git a/feature_integration_tests/test_cases/requirements.txt.lock b/feature_integration_tests/test_cases/requirements.txt.lock index 3eb053f6e25..cfd30002c1a 100644 --- a/feature_integration_tests/test_cases/requirements.txt.lock +++ b/feature_integration_tests/test_cases/requirements.txt.lock @@ -2,22 +2,17 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# bazel run //feature_integration_tests/python_test_cases:requirements.update +# bazel run //feature_integration_tests/test_cases:requirements.update # -basedpyright==1.29.2 \ - --hash=sha256:12c49186003b9f69a028615da883ef97035ea2119a9e3f93a00091b3a27088a6 \ - --hash=sha256:f389e2997de33d038c5065fd85bff351fbdc62fa6d6371c7b947fc3bce8d437d - # via -r /home/pko/.cache/bazel/_bazel_pko/2af2ff4db91047a487505aa8f91f8f54/external/score_tooling+/python_basics/requirements.txt -iniconfig==2.1.0 \ - --hash=sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7 \ - --hash=sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760 - # via - # -r /home/pko/.cache/bazel/_bazel_pko/2af2ff4db91047a487505aa8f91f8f54/external/score_tooling+/python_basics/requirements.txt - # pytest +basedpyright==1.35.0 \ + --hash=sha256:2a7e0bd476623d48499e2b18ff6ed19dc28c51909cf9e1152ad355b5809049ad \ + --hash=sha256:4f4f84023df5a0cd4ee154916ba698596682ac98bacfa22c941ed6aaf07bba4e +iniconfig==2.3.0 \ + --hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730 \ + --hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 - # via pytest-html markupsafe==3.0.2 \ --hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \ --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \ @@ -80,54 +75,37 @@ markupsafe==3.0.2 \ --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \ --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \ --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50 - # via jinja2 -nodejs-wheel-binaries==22.16.0 \ - --hash=sha256:2728972d336d436d39ee45988978d8b5d963509e06f063e80fe41b203ee80b28 \ - --hash=sha256:2fffb4bf1066fb5f660da20819d754f1b424bca1b234ba0f4fa901c52e3975fb \ - --hash=sha256:447ad796850eb52ca20356ad39b2d296ed8fef3f214921f84a1ccdad49f2eba1 \ - --hash=sha256:4ae3cf22138891cb44c3ee952862a257ce082b098b29024d7175684a9a77b0c0 \ - --hash=sha256:71f2de4dc0b64ae43e146897ce811f80ac4f9acfbae6ccf814226282bf4ef174 \ - --hash=sha256:7f526ca6a132b0caf633566a2a78c6985fe92857e7bfdb37380f76205a10b808 \ - --hash=sha256:986b715a96ed703f8ce0c15712f76fc42895cf09067d72b6ef29e8b334eccf64 \ - --hash=sha256:d695832f026df3a0cf9a089d222225939de9d1b67f8f0a353b79f015aabbe7e2 \ - --hash=sha256:dbfccbcd558d2f142ccf66d8c3a098022bf4436db9525b5b8d32169ce185d99e - # via - # -r /home/pko/.cache/bazel/_bazel_pko/2af2ff4db91047a487505aa8f91f8f54/external/score_tooling+/python_basics/requirements.txt - # basedpyright +nodejs-wheel-binaries==24.11.1 \ + --hash=sha256:0e14874c3579def458245cdbc3239e37610702b0aa0975c1dc55e2cb80e42102 \ + --hash=sha256:10197b1c9c04d79403501766f76508b0dac101ab34371ef8a46fcf51773497d0 \ + --hash=sha256:376b9ea1c4bc1207878975dfeb604f7aa5668c260c6154dcd2af9d42f7734116 \ + --hash=sha256:413dfffeadfb91edb4d8256545dea797c237bba9b3faefea973cde92d96bb922 \ + --hash=sha256:5ef598101b0fb1c2bf643abb76dfbf6f76f1686198ed17ae46009049ee83c546 \ + --hash=sha256:78bc5bb889313b565df8969bb7423849a9c7fc218bf735ff0ce176b56b3e96f0 \ + --hash=sha256:c2741525c9874b69b3e5a6d6c9179a6fe484ea0c3d5e7b7c01121c8e5d78b7e2 \ + --hash=sha256:c79a7e43869ccecab1cae8183778249cceb14ca2de67b5650b223385682c6239 \ + --hash=sha256:cde41d5e4705266688a8d8071debf4f8a6fcea264c61292782672ee75a6905f9 packaging==25.0 \ --hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \ --hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f - # via - # -r /home/pko/.cache/bazel/_bazel_pko/2af2ff4db91047a487505aa8f91f8f54/external/score_tooling+/python_basics/requirements.txt - # pytest pluggy==1.6.0 \ --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ --hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 - # via - # -r /home/pko/.cache/bazel/_bazel_pko/2af2ff4db91047a487505aa8f91f8f54/external/score_tooling+/python_basics/requirements.txt - # pytest -pytest==8.3.5 \ - --hash=sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820 \ - --hash=sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845 - # via - # -r /home/pko/.cache/bazel/_bazel_pko/2af2ff4db91047a487505aa8f91f8f54/external/score_tooling+/python_basics/requirements.txt - # pytest-html - # pytest-metadata - # pytest-repeat - # testing-utils +pygments==2.19.2 \ + --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ + --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pytest==9.0.1 \ + --hash=sha256:3e9c069ea73583e255c3b21cf46b8d3c56f6e3a1a8f6da94ccb0fcf57b9d73c8 \ + --hash=sha256:67be0030d194df2dfa7b556f2e56fb3c3315bd5c8822c6951162b92b32ce7dad pytest-html==4.1.1 \ --hash=sha256:70a01e8ae5800f4a074b56a4cb1025c8f4f9b038bba5fe31e3c98eb996686f07 \ --hash=sha256:c8152cea03bd4e9bee6d525573b67bbc6622967b72b9628dda0ea3e2a0b5dd71 - # via testing-utils pytest-metadata==3.1.1 \ --hash=sha256:c8e0844db684ee1c798cfa38908d20d67d0463ecb6137c72e91f418558dd5f4b \ --hash=sha256:d2a29b0355fbc03f168aa96d41ff88b1a3b44a3b02acbe491801c98a048017c8 - # via pytest-html pytest-repeat==0.9.4 \ --hash=sha256:c1738b4e412a6f3b3b9e0b8b29fcd7a423e50f87381ad9307ef6f5a8601139f3 \ --hash=sha256:d92ac14dfaa6ffcfe6917e5d16f0c9bc82380c135b03c2a5f412d2637f224485 - # via testing-utils # WARNING: pip install will require the following package to be hashed. # Consider using a hashable URL like https://github.com/jazzband/pip-tools/archive/SOMECOMMIT.zip testing-utils @ git+https://github.com/eclipse-score/testing_tools.git@v0.3.0 - # via -r feature_integration_tests/python_test_cases/requirements.txt diff --git a/scripts/tooling/BUILD b/scripts/tooling/BUILD index 61466b85d8f..c2088414897 100644 --- a/scripts/tooling/BUILD +++ b/scripts/tooling/BUILD @@ -15,17 +15,21 @@ load("@rules_python//python:defs.bzl", "py_binary", "py_library") load("@rules_python//python:pip.bzl", "compile_pip_requirements") load("@score_tooling//python_basics:defs.bzl", "score_py_pytest") -# In order to update the requirements, change the `requirements.in` file and run: -# `bazel run //src:requirements.update`. -# This will update the `requirements.txt` file. -# To upgrade all dependencies to their latest versions, run: -# `bazel run //src:requirements.update -- --upgrade`. +# In order to update the requirements, change the `requirements.in` file and run +# `bazel run //scripts/tooling:requirements.update` +# This will update the `requirements.txt` file +# To upgrade all dependencies to their latest versions, run +# `bazel run //scripts/tooling:requirements.update -- --upgrade` + compile_pip_requirements( name = "requirements", srcs = [ "requirements.in", "@score_tooling//python_basics:requirements.txt", ], + extra_args = [ + "--no-annotate", + ], requirements_txt = "requirements.txt", tags = [ "manual", @@ -58,6 +62,25 @@ py_binary( deps = [":cli"], ) +# Workflow scripts as executables +py_binary( + name = "checkout_repos", + srcs = ["cli/workflow/checkout_repos.py"], + main = "cli/workflow/checkout_repos.py", + visibility = ["//visibility:public"], + deps = [ + ":cli", + ":lib", + ] + all_requirements, +) + +py_binary( + name = "recategorize_guidelines", + srcs = ["cli/workflow/recategorize_guidelines.py"], + main = "cli/workflow/recategorize_guidelines.py", + visibility = ["//visibility:public"], +) + # Tests target score_py_pytest( name = "tooling_tests", diff --git a/scripts/tooling/cli/workflow/__init__.py b/scripts/tooling/cli/workflow/__init__.py new file mode 100644 index 00000000000..ca5de742e9c --- /dev/null +++ b/scripts/tooling/cli/workflow/__init__.py @@ -0,0 +1,12 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* diff --git a/scripts/tooling/cli/workflow/checkout_repos.py b/scripts/tooling/cli/workflow/checkout_repos.py new file mode 100755 index 00000000000..ad701e5076b --- /dev/null +++ b/scripts/tooling/cli/workflow/checkout_repos.py @@ -0,0 +1,109 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + +""" +Checkout all pinned repositories for CodeQL analysis. + +Clones repositories directly from known_good.json using GitPython library +with GitHub token authentication to avoid rate limits. +""" + +import logging +import os +import sys +from pathlib import Path + +from scripts.tooling.lib.git_operations import shallow_clone_repository +from scripts.tooling.lib.known_good import load_known_good + +_LOG = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO, format="%(message)s") + + +def checkout_repo(name: str, url: str, ref: str, path: Path) -> None: + """ + Checkout a single repository using git_operations library. + + Args: + name: Repository name + url: Repository URL + ref: Git reference (branch, tag, or commit hash) + path: Local path to checkout into + + Raises: + Exception: If checkout fails + """ + _LOG.info(f"Checking out {name} ({ref}) to {path}") + + shallow_clone_repository(url=url, path=path, ref=ref) + + +def main() -> int: + """Main entry point for standalone execution.""" + # When running with bazel, use BUILD_WORKING_DIRECTORY to find workspace root + workspace_root = Path(os.environ.get("BUILD_WORKING_DIRECTORY", ".")) + known_good_path = workspace_root / "known_good.json" + + if not known_good_path.exists(): + _LOG.error(f"known_good.json not found at {known_good_path}") + return 1 + + try: + known_good = load_known_good(known_good_path) + except Exception as e: + _LOG.error(f"Failed to parse known_good.json: {e}") + return 1 + + # Extract target_sw modules + modules = known_good.modules.get("target_sw", {}) + repo_count = len(modules) + + _LOG.info(f"Checking out {repo_count} repositories from known_good.json...") + + # Track successfully checked out repositories + repo_paths = [] + + # Checkout each repository + for name, module in modules.items(): + url = module.repo + ref = module.version or module.branch or module.hash + # Use workspace-relative path + path = workspace_root / "repos" / name + + try: + checkout_repo(name, url, ref, path) + repo_paths.append(str(path)) + except Exception as e: + _LOG.error(f"Failed to checkout {name}: {e}") + return 1 + + # Output all paths (comma-separated for GitHub Actions compatibility) + repo_paths_output = ",".join(repo_paths) + + # Write to GITHUB_OUTPUT if available + github_output = os.environ.get("GITHUB_OUTPUT") + if github_output: + try: + with open(github_output, "a") as f: + f.write(f"repo_paths={repo_paths_output}\n") + except IOError as e: + _LOG.warning(f"Failed to write GITHUB_OUTPUT: {e}") + + # Log summary + _LOG.info(f"Successfully checked out {len(repo_paths)} of {repo_count} repositories") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/tooling/cli/workflow/recategorize_guidelines.py b/scripts/tooling/cli/workflow/recategorize_guidelines.py new file mode 100755 index 00000000000..59d170fb969 --- /dev/null +++ b/scripts/tooling/cli/workflow/recategorize_guidelines.py @@ -0,0 +1,227 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* + +""" +Recategorize CodeQL SARIF results according to coding standards. +""" + +import json +import re +import subprocess +import sys +from pathlib import Path + + +# Configuration paths +RECATEGORIZE_SCRIPT = "codeql-coding-standards-repo/scripts/guideline_recategorization/recategorize.py" +CODING_STANDARDS_CONFIG = "./.github/codeql/coding-standards.yml" +CODING_STANDARDS_SCHEMA = "codeql-coding-standards-repo/schemas/coding-standards-schema-1.0.0.json" +SARIF_SCHEMA = "codeql-coding-standards-repo/schemas/sarif-schema-2.1.0.json" +SARIF_FILE = "sarif-results/cpp.sarif" +OUTPUT_DIR = "sarif-results-recategorized" + + +def validate_paths(): + """ + Validate that required files exist. + + Note: Only validates files needed for recategorization if SARIF exists. + Returns: + True if validation passes or SARIF doesn't exist, False on critical errors + """ + # First check if SARIF file exists - if not, nothing to recategorize + if not Path(SARIF_FILE).exists(): + print(f"Info: SARIF file not found at {SARIF_FILE}", file=sys.stderr) + return False # Signal to skip recategorization + + # SARIF exists, check for recategorization dependencies + optional_files = [ + RECATEGORIZE_SCRIPT, + CODING_STANDARDS_SCHEMA, + SARIF_SCHEMA, + ] + + required_files = [ + CODING_STANDARDS_CONFIG, + ] + + # Check required files (fail if missing) + for file_path in required_files: + if not Path(file_path).exists(): + print(f"Error: Required file not found: {file_path}", file=sys.stderr) + return False + + # Warn about optional files but don't fail + missing_optional = [] + for file_path in optional_files: + if not Path(file_path).exists(): + missing_optional.append(file_path) + + if missing_optional: + print(f"Warning: Some recategorization files not found: {missing_optional}", file=sys.stderr) + print("Recategorization will be skipped, but filtering will still be applied.", file=sys.stderr) + + return True + + +def recategorize_sarif(): + """ + Run the CodeQL recategorization script on SARIF results. + + Returns: + True if successful or skipped, False on critical errors + """ + # Check if recategorization script exists + if not Path(RECATEGORIZE_SCRIPT).exists(): + print(f"Info: Recategorization script not found at {RECATEGORIZE_SCRIPT}", file=sys.stderr) + print("Skipping recategorization step (will apply filtering only).", file=sys.stderr) + return True # Not a failure, just skip this step + + # Create output directory + output_path = Path(OUTPUT_DIR) + output_path.mkdir(parents=True, exist_ok=True) + + output_file = output_path / Path(SARIF_FILE).name + + print(f"Processing {SARIF_FILE} for recategorization...") + + try: + # Run recategorization script + result = subprocess.run( + [ + sys.executable, + RECATEGORIZE_SCRIPT, + "--coding-standards-schema-file", + CODING_STANDARDS_SCHEMA, + "--sarif-schema-file", + SARIF_SCHEMA, + CODING_STANDARDS_CONFIG, + SARIF_FILE, + str(output_file), + ], + check=True, + capture_output=True, + text=True, + ) + + print("Recategorization completed successfully") + if result.stdout: + print("Output:", result.stdout) + + # Replace original SARIF file with recategorized version + sarif_path = Path(SARIF_FILE) + + if sarif_path.exists(): + sarif_path.unlink() + print(f"Removed original {SARIF_FILE}") + + # Move recategorized file to original location + output_file.replace(sarif_path) + print(f"Moved recategorized SARIF to {SARIF_FILE}") + + return True + + except subprocess.CalledProcessError as e: + print(f"Error: Recategorization script failed: {e}", file=sys.stderr) + if e.stderr: + print(f"Error output: {e.stderr}", file=sys.stderr) + return False + except (FileNotFoundError, OSError) as e: + print(f"Error: File operation failed: {e}", file=sys.stderr) + return False + + +def filter_sarif_results(): + """ + Filter SARIF results to only include entries with paths matching repos/*. + + Returns: + True if successful, False otherwise + """ + sarif_path = Path(SARIF_FILE) + + if not sarif_path.exists(): + print(f"Warning: SARIF file not found: {SARIF_FILE}", file=sys.stderr) + return False + + try: + # Load SARIF file + with open(sarif_path, "r") as f: + sarif_data = json.load(f) + + print("Filtering SARIF results to only include entries with paths matching repos/* ...") + + # Filter runs and results + if "runs" in sarif_data: + for run in sarif_data["runs"]: + if "results" in run: + filtered_results = [] + + for result in run["results"]: + # Check if result has locations + locations = result.get("locations", []) + if not locations: + continue + + # Check if first location URI matches repos/ pattern + first_location = locations[0].get("physicalLocation", {}) + artifact_uri = first_location.get("artifactLocation", {}).get("uri", "") + + # Pattern: (^|/)repos/ - matches repos/ at start or after a / + if artifact_uri and re.search(r"(^|/)repos/", artifact_uri): + filtered_results.append(result) + + # Update results with filtered list + run["results"] = filtered_results + print( + f"Run '{run.get('tool', {}).get('driver', {}).get('name', 'unknown')}' " + f"now has {len(filtered_results)} results" + ) + + # Write filtered SARIF back to file + with open(sarif_path, "w") as f: + json.dump(sarif_data, f, indent=2) + + print(f"Filtered SARIF written to {SARIF_FILE}") + return True + + except (json.JSONDecodeError, IOError) as e: + print(f"Error: Failed to filter SARIF file: {e}", file=sys.stderr) + return False + + +def main(): + """Main entry point.""" + # Validate required files exist + has_sarif = validate_paths() + + if not has_sarif: + # No SARIF file to process - this is normal before CodeQL analysis runs + print("No SARIF file found - skipping recategorization.") + print("This is expected if CodeQL analysis hasn't completed yet.") + sys.exit(0) + + # Run recategorization (will skip gracefully if script not available) + if not recategorize_sarif(): + print("Warning: Recategorization failed, continuing with filtering...", file=sys.stderr) + + # Filter SARIF results to only include repos/* + if not filter_sarif_results(): + sys.exit(1) + + print("Recategorization workflow completed successfully") + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/scripts/tooling/lib/git_operations.py b/scripts/tooling/lib/git_operations.py new file mode 100644 index 00000000000..ddde9a0f019 --- /dev/null +++ b/scripts/tooling/lib/git_operations.py @@ -0,0 +1,118 @@ +# ******************************************************************************* +# 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 +# ******************************************************************************* +""" +Git operations library for repository checkout. + +Provides functions to clone repositories using GitPython library with GitHub token +authentication to avoid rate limits. +""" + +import logging +import os +import re +from pathlib import Path +from typing import Optional + +import git +from git import Repo + +_LOG = logging.getLogger(__name__) + + +def is_commit_hash(ref: str) -> bool: + """ + Check if reference looks like a commit hash (40 hex characters for SHA-1). + + Args: + ref: Git reference (branch, tag, or hash) + + Returns: + True if ref matches commit hash pattern + """ + return bool(re.match(r"^[0-9a-fA-F]{40}$", ref)) + + +def get_authenticated_url(url: str, token: Optional[str] = None) -> str: + """ + Add authentication token to GitHub URL. + + Args: + url: Repository URL + token: GitHub token (if None, uses GITHUB_TOKEN env var) + + Returns: + URL with embedded authentication token + """ + if token is None: + token = os.environ.get("GITHUB_TOKEN", "") + + if token and "github.com" in url: + # Replace https://github.com/ with https://token@github.com/ + return url.replace("https://github.com/", f"https://{token}@github.com/") + return url + + +def shallow_clone_repository(url: str, path: Path, ref: Optional[str] = None, token: Optional[str] = None) -> None: + """ + Perform a shallow clone of a repository using GitPython library. + + Uses GitPython with GitHub token authentication to avoid rate limits. + + Args: + url: Repository URL + path: Local path to clone into + ref: Optional git reference (branch, tag, or commit hash) + token: Optional GitHub token (uses GITHUB_TOKEN env if not provided) + + Raises: + git.exc.GitCommandError: If git clone/fetch/checkout fails + Exception: For other unexpected errors + """ + path.parent.mkdir(parents=True, exist_ok=True) + auth_url = get_authenticated_url(url, token) + + if ref and is_commit_hash(ref): + # For commit hashes, clone with depth 1 then fetch specific commit + _LOG.info(f"Cloning {url} with shallow depth (commit hash: {ref[:8]}...)") + + # Clone with depth 1 and all branches + repo = Repo.clone_from(auth_url, str(path), depth=1, no_single_branch=True) + + # Fetch the specific commit + _LOG.info(f"Fetching specific commit {ref[:8]}...") + origin = repo.remotes.origin + origin.fetch(ref, depth=1) + + # Checkout the commit + repo.git.checkout(ref) + _LOG.info(f"Successfully checked out commit {ref[:8]}") + + elif ref: + # For branches/tags, use branch parameter for shallow clone + _LOG.info(f"Cloning {url} with branch/tag {ref}") + try: + Repo.clone_from(auth_url, str(path), branch=ref, depth=1) + _LOG.info(f"Successfully cloned branch/tag {ref}") + except git.exc.GitCommandError: + # Try with 'v' prefix if it looks like a version number + if not ref.startswith("v") and re.match(r"^\d+\.\d+", ref): + _LOG.info(f"Retrying with 'v' prefix: v{ref}") + Repo.clone_from(auth_url, str(path), branch=f"v{ref}", depth=1) + _LOG.info(f"Successfully cloned branch/tag v{ref}") + else: + raise + else: + # No ref specified, clone default branch + _LOG.info(f"Cloning {url} (default branch)") + Repo.clone_from(auth_url, str(path), depth=1) + _LOG.info("Successfully cloned default branch") diff --git a/scripts/tooling/requirements.in b/scripts/tooling/requirements.in index c6057dcbb85..a4ee406fd56 100644 --- a/scripts/tooling/requirements.in +++ b/scripts/tooling/requirements.in @@ -1,2 +1,3 @@ jinja2 >= 3 PyGithub>=2.1.1 +GitPython>=3.1.0 diff --git a/scripts/tooling/requirements.txt b/scripts/tooling/requirements.txt index 72c89ec11a2..90d02660ceb 100644 --- a/scripts/tooling/requirements.txt +++ b/scripts/tooling/requirements.txt @@ -7,11 +7,9 @@ basedpyright==1.35.0 \ --hash=sha256:2a7e0bd476623d48499e2b18ff6ed19dc28c51909cf9e1152ad355b5809049ad \ --hash=sha256:4f4f84023df5a0cd4ee154916ba698596682ac98bacfa22c941ed6aaf07bba4e - # via -r /home/pawel/.cache/bazel/_bazel_pawel/3b31b706077f58aabe34be25f25c80e9/external/score_tooling+/python_basics/requirements.txt certifi==2026.2.25 \ --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 - # via requests cffi==2.0.0 \ --hash=sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb \ --hash=sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b \ @@ -97,9 +95,6 @@ cffi==2.0.0 \ --hash=sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5 \ --hash=sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453 \ --hash=sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf - # via - # cryptography - # pynacl charset-normalizer==3.4.5 \ --hash=sha256:014837af6fabf57121b6254fa8ade10dceabc3528b27b721a64bbc7b8b1d4eb4 \ --hash=sha256:01a1ed54b953303ca7e310fafe0fe347aab348bd81834a0bcd602eb538f89d66 \ @@ -214,7 +209,6 @@ charset-normalizer==3.4.5 \ --hash=sha256:f8102ae93c0bc863b1d41ea0f4499c20a83229f52ed870850892df555187154a \ --hash=sha256:fc1c64934b8faf7584924143eb9db4770bbdb16659626e1a1a4d9efbcb68d947 \ --hash=sha256:ff95a9283de8a457e6b12989de3f9f5193430f375d64297d323a615ea52cbdb3 - # via requests cryptography==46.0.5 \ --hash=sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72 \ --hash=sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235 \ @@ -265,21 +259,21 @@ cryptography==46.0.5 \ --hash=sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2 \ --hash=sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2 \ --hash=sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87 - # via pyjwt +gitdb==4.0.12 \ + --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \ + --hash=sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf +gitpython==3.1.46 \ + --hash=sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f \ + --hash=sha256:79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058 idna==3.11 \ --hash=sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea \ --hash=sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902 - # via requests iniconfig==2.3.0 \ --hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730 \ --hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 - # via - # -r /home/pawel/.cache/bazel/_bazel_pawel/3b31b706077f58aabe34be25f25c80e9/external/score_tooling+/python_basics/requirements.txt - # pytest jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 - # via -r scripts/tooling/requirements.in markupsafe==3.0.3 \ --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ --hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \ @@ -370,7 +364,6 @@ markupsafe==3.0.3 \ --hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 - # via jinja2 nodejs-wheel-binaries==24.11.1 \ --hash=sha256:0e14874c3579def458245cdbc3239e37610702b0aa0975c1dc55e2cb80e42102 \ --hash=sha256:10197b1c9c04d79403501766f76508b0dac101ab34371ef8a46fcf51773497d0 \ @@ -381,39 +374,24 @@ nodejs-wheel-binaries==24.11.1 \ --hash=sha256:c2741525c9874b69b3e5a6d6c9179a6fe484ea0c3d5e7b7c01121c8e5d78b7e2 \ --hash=sha256:c79a7e43869ccecab1cae8183778249cceb14ca2de67b5650b223385682c6239 \ --hash=sha256:cde41d5e4705266688a8d8071debf4f8a6fcea264c61292782672ee75a6905f9 - # via - # -r /home/pawel/.cache/bazel/_bazel_pawel/3b31b706077f58aabe34be25f25c80e9/external/score_tooling+/python_basics/requirements.txt - # basedpyright packaging==25.0 \ --hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \ --hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f - # via - # -r /home/pawel/.cache/bazel/_bazel_pawel/3b31b706077f58aabe34be25f25c80e9/external/score_tooling+/python_basics/requirements.txt - # pytest pluggy==1.6.0 \ --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ --hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 - # via - # -r /home/pawel/.cache/bazel/_bazel_pawel/3b31b706077f58aabe34be25f25c80e9/external/score_tooling+/python_basics/requirements.txt - # pytest pycparser==3.0 \ --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \ --hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992 - # via cffi pygithub==2.8.1 \ --hash=sha256:23a0a5bca93baef082e03411bf0ce27204c32be8bfa7abc92fe4a3e132936df0 \ --hash=sha256:341b7c78521cb07324ff670afd1baa2bf5c286f8d9fd302c1798ba594a5400c9 - # via -r scripts/tooling/requirements.in pygments==2.19.2 \ --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b - # via - # -r /home/pawel/.cache/bazel/_bazel_pawel/3b31b706077f58aabe34be25f25c80e9/external/score_tooling+/python_basics/requirements.txt - # pytest pyjwt[crypto]==2.11.0 \ --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 - # via pygithub pynacl==1.6.2 \ --hash=sha256:018494d6d696ae03c7e656e5e74cdfd8ea1326962cc401bcf018f1ed8436811c \ --hash=sha256:04316d1fc625d860b6c162fff704eb8426b1a8bcd3abacea11142cbd99a6b574 \ @@ -440,22 +418,18 @@ pynacl==1.6.2 \ --hash=sha256:d071c6a9a4c94d79eb665db4ce5cedc537faf74f2355e4d502591d850d3913c0 \ --hash=sha256:d29bfe37e20e015a7d8b23cfc8bd6aa7909c92a1b8f41ee416bbb3e79ef182b2 \ --hash=sha256:fe9847ca47d287af41e82be1dd5e23023d3c31a951da134121ab02e42ac218c9 - # via pygithub pytest==9.0.1 \ --hash=sha256:3e9c069ea73583e255c3b21cf46b8d3c56f6e3a1a8f6da94ccb0fcf57b9d73c8 \ --hash=sha256:67be0030d194df2dfa7b556f2e56fb3c3315bd5c8822c6951162b92b32ce7dad - # via -r /home/pawel/.cache/bazel/_bazel_pawel/3b31b706077f58aabe34be25f25c80e9/external/score_tooling+/python_basics/requirements.txt requests==2.32.5 \ --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf - # via pygithub +smmap==5.0.3 \ + --hash=sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c \ + --hash=sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f typing-extensions==4.15.0 \ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 - # via pygithub urllib3==2.6.3 \ --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \ --hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4 - # via - # pygithub - # requests diff --git a/scripts/workflow/checkout_repos.sh b/scripts/workflow/checkout_repos.sh deleted file mode 100755 index d70cce8bc08..00000000000 --- a/scripts/workflow/checkout_repos.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash -# ******************************************************************************* -# Copyright (c) 2025 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 -# ******************************************************************************* -# jq is already installed by the previous step. - -# Read repositories from the repos.json file created by the previous step -repos=$(cat repos.json) -repo_count=$(echo "$repos" | jq length) -# Initialize an empty string for paths to be outputted -repo_paths_output="" -for i in $(seq 0 $((repo_count-1))); do - name=$(echo "$repos" | jq -r ".[$i].name") - url=$(echo "$repos" | jq -r ".[$i].url") - ref=$(echo "$repos" | jq -r ".[$i].version") # This can be a branch, tag, or commit hash - path=$(echo "$repos" | jq -r ".[$i].path") # e.g., "repos/score_baselibs" - echo "Checking out $name ($ref) to $path" - # Create the parent directory if it doesn't exist - mkdir -p "$(dirname "$path")" - # Check if 'ref' looks like a commit hash (e.g., 40 hex characters) - # This is a heuristic; a more robust check might involve fetching refs first. - if [[ "$ref" =~ ^[0-9a-fA-F]{40}$ ]]; then - echo " Detected commit hash. Cloning and then checking out." - git clone "$url" "$path" - (cd "$path" && git checkout "$ref") - else - echo " Detected branch/tag. Cloning with --branch." - git clone --depth 1 --branch v"$ref" "$url" "$path" - fi - # Append the path to the list, separated by commas - if [ -z "$repo_paths_output" ]; then - repo_paths_output="$path" - else - repo_paths_output="$repo_paths_output,$path" - fi -done -# Output all paths as a single variable -echo "repo_paths=$repo_paths_output" >> $GITHUB_OUTPUT diff --git a/scripts/workflow/parse_repos.sh b/scripts/workflow/parse_repos.sh deleted file mode 100755 index 71c50737a5e..00000000000 --- a/scripts/workflow/parse_repos.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# ******************************************************************************* -# Copyright (c) 2025 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 -# ******************************************************************************* -sudo apt-get update && sudo apt-get install -y jq -JSON_FILE="./known_good.json" -# Check if the file exists -if [ ! -f "$JSON_FILE" ]; then - echo "Error file not found '$JSON_FILE' " - ls -la . - exit 1 -fi -# Create repos.json from known_good.json -# This jq command transforms the 'modules' object into an array of repository objects -# with 'name', 'url', 'version' (branch/tag/hash), and 'path'. -jq '[.modules.target_sw | to_entries[] | { - name: .key, - url: .value.repo, - version: (.value.branch // .value.hash // .value.version), - path: ("repos/" + .key) -}]' "$JSON_FILE" > repos.json -echo "Generated repos.json:" -cat repos.json -echo "" # Add a newline for better readability -# The following GITHUB_OUTPUT variables are set for each module. -# These might be useful for other steps, but are not directly used by the 'checkout-repos' step -# which now reads 'repos.json' directly. -echo "MODULE_COUNT=$(jq '.modules.target_sw | length' "$JSON_FILE")" >> $GITHUB_OUTPUT -jq -c '.modules.target_sw | to_entries[]' "$JSON_FILE" | while read -r module_entry; do - module_name=$(echo "$module_entry" | jq -r '.key') - repo_url=$(echo "$module_entry" | jq -r '.value.repo // empty') - version=$(echo "$module_entry" | jq -r '.value.version // empty') - branch=$(echo "$module_entry" | jq -r '.value.branch // empty') - hash=$(echo "$module_entry" | jq -r '.value.hash // empty') - echo "${module_name}_url=$repo_url" >> $GITHUB_OUTPUT - if [ -n "$version" ]; then - echo "${module_name}_version=$version" >> $GITHUB_OUTPUT - fi - if [ -n "$branch" ]; then - echo "${module_name}_branch=$branch" >> $GITHUB_OUTPUT - fi - if [ -n "$hash" ]; then - echo "${module_name}_hash=$hash" >> $GITHUB_OUTPUT - fi -done diff --git a/scripts/workflow/recategorize_guidelines.sh b/scripts/workflow/recategorize_guidelines.sh deleted file mode 100755 index 8fa4b736020..00000000000 --- a/scripts/workflow/recategorize_guidelines.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -# ******************************************************************************* -# Copyright (c) 2025 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 -# ******************************************************************************* -RECATEGORIZE_SCRIPT="codeql-coding-standards-repo/scripts/guideline_recategorization/recategorize.py" -CODING_STANDARDS_CONFIG="./.github/codeql/coding-standards.yml" -CODING_STANDARDS_SCHEMA="codeql-coding-standards-repo/schemas/coding-standards-schema-1.0.0.json" -SARIF_SCHEMA="codeql-coding-standards-repo/schemas/sarif-schema-2.1.0.json" -SARIF_FILE="sarif-results/cpp.sarif" -mkdir -p sarif-results-recategorized -echo "Processing $SARIF_FILE for recategorization..." -python3 "$RECATEGORIZE_SCRIPT" \ - --coding-standards-schema-file "$CODING_STANDARDS_SCHEMA" \ - --sarif-schema-file "$SARIF_SCHEMA" \ - "$CODING_STANDARDS_CONFIG" \ - "$SARIF_FILE" \ - "sarif-results-recategorized/$(basename "$SARIF_FILE")" - rm "$SARIF_FILE" - mv "sarif-results-recategorized/$(basename "$SARIF_FILE")" "$SARIF_FILE" From 0605a5bbce2541d3b6bf17f31cc2f5202ef93116 Mon Sep 17 00:00:00 2001 From: Saumya-R Date: Thu, 16 Apr 2026 17:59:05 +0530 Subject: [PATCH 2/2] adding newest version --- .github/workflows/codeql-multiple-repo-scan.yml | 3 ++- scripts/tooling/cli/workflow/checkout_repos.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-multiple-repo-scan.yml b/.github/workflows/codeql-multiple-repo-scan.yml index 6ec2ece8c66..696a2687178 100644 --- a/.github/workflows/codeql-multiple-repo-scan.yml +++ b/.github/workflows/codeql-multiple-repo-scan.yml @@ -63,7 +63,7 @@ jobs: with: languages: cpp build-mode: none - packs: codeql/misra-cpp-coding-standards + packs: codeql/misra-cpp-coding-standards@2.57.0 config-file: ./.github/codeql/codeql-config.yml - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 @@ -81,6 +81,7 @@ jobs: with: repository: github/codeql-coding-standards path: codeql-coding-standards-repo + ref: v2.57.0 - name: Recategorize Guidelines if: always() run: | diff --git a/scripts/tooling/cli/workflow/checkout_repos.py b/scripts/tooling/cli/workflow/checkout_repos.py index ad701e5076b..bc89f01ce9d 100755 --- a/scripts/tooling/cli/workflow/checkout_repos.py +++ b/scripts/tooling/cli/workflow/checkout_repos.py @@ -76,7 +76,8 @@ def main() -> int: # Checkout each repository for name, module in modules.items(): url = module.repo - ref = module.version or module.branch or module.hash + # Prioritize hash and version over branch to ensure pinned commits + ref = module.hash or module.version or module.branch # Use workspace-relative path path = workspace_root / "repos" / name