1+ # *******************************************************************************
2+ # Copyright (c) 2025 Contributors to the Eclipse Foundation
3+ #
4+ # See the NOTICE file(s) distributed with this work for additional
5+ # information regarding copyright ownership.
6+ #
7+ # This program and the accompanying materials are made available under the
8+ # terms of the Apache License Version 2.0 which is available at
9+ # https://www.apache.org/licenses/LICENSE-2.0
10+ #
11+ # SPDX-License-Identifier: Apache-2.0
12+ # *******************************************************************************
13+
14+ name : " CodeQL - Multi-Repo Source Scan"
15+
16+ on :
17+ pull_request :
18+ types : [opened, reopened, synchronize]
19+ merge_group :
20+ types : [checks_requested]
21+
22+ permissions :
23+ contents : write
24+
25+ jobs :
26+ analyze-repos :
27+ name : Analyze Multiple Repositories
28+ runs-on : ubuntu-latest
29+ permissions :
30+ security-events : write
31+ packages : read
32+ actions : read
33+ contents : read
34+
35+ steps :
36+ - name : Checkout central repository
37+ uses : actions/checkout@v4
38+
39+ - name : Checkout CodeQL Coding Standards scripts
40+ uses : actions/checkout@v4
41+ with :
42+ repository : github/codeql-coding-standards
43+ path : codeql-coding-standards-repo # Klonen in diesen Ordner
44+ ref : main # Oder eine spezifische Release-Version, z.B. 'v2.53.0-dev'
45+
46+ # Add coding standard packages and dependencies
47+ - name : Install Python dependencies for Coding Standards scripts
48+ run : |
49+ python3 -m pip install --upgrade pip
50+ pip3 install pyyaml jsonpath-ng jsonschema jsonpatch jsonpointer pytest sarif-tools
51+
52+ - name : Parse known_good.json and create repos.json
53+ id : parse-repos
54+ run : |
55+ sudo apt-get update && sudo apt-get install -y jq
56+ JSON_FILE="./known_good.json"
57+
58+ # Check if the file exists
59+ if [ ! -f "$JSON_FILE" ]; then
60+ echo "Error file not found '$JSON_FILE' "
61+ ls -la .
62+ exit 1
63+ fi
64+
65+ # Create repos.json from known_good.json
66+ # This jq command transforms the 'modules' object into an array of repository objects
67+ # with 'name', 'url', 'version' (branch/tag/hash), and 'path'.
68+ jq '[.modules | to_entries[] | {
69+ name: .key,
70+ url: .value.repo,
71+ version: (.value.branch // .value.hash // .value.version),
72+ path: ("repos/" + .key)
73+ }]' "$JSON_FILE" > repos.json
74+
75+ echo "Generated repos.json:"
76+ cat repos.json
77+ echo "" # Add a newline for better readability
78+
79+ # The following GITHUB_OUTPUT variables are set for each module.
80+ # These might be useful for other steps, but are not directly used by the 'checkout-repos' step
81+ # which now reads 'repos.json' directly.
82+ echo "MODULE_COUNT=$(jq '.modules | length' "$JSON_FILE")" >> $GITHUB_OUTPUT
83+
84+ jq -c '.modules | to_entries[]' "$JSON_FILE" | while read -r module_entry; do
85+ module_name=$(echo "$module_entry" | jq -r '.key')
86+ repo_url=$(echo "$module_entry" | jq -r '.value.repo // empty')
87+ version=$(echo "$module_entry" | jq -r '.value.version // empty')
88+ branch=$(echo "$module_entry" | jq -r '.value.branch // empty')
89+ hash=$(echo "$module_entry" | jq -r '.value.hash // empty')
90+
91+ echo "${module_name}_url=$repo_url" >> $GITHUB_OUTPUT
92+
93+ if [ -n "$version" ]; then
94+ echo "${module_name}_version=$version" >> $GITHUB_OUTPUT
95+ fi
96+
97+ if [ -n "$branch" ]; then
98+ echo "${module_name}_branch=$branch" >> $GITHUB_OUTPUT
99+ fi
100+
101+ if [ -n "$hash" ]; then
102+ echo "${module_name}_hash=$hash" >> $GITHUB_OUTPUT
103+ fi
104+ done
105+
106+ - name : Checkout all pinned repositories
107+ id : checkout-repos
108+ run : |
109+ # jq is already installed by the previous step.
110+
111+ # Read repositories from the repos.json file created by the previous step
112+ repos=$(cat repos.json)
113+ repo_count=$(echo "$repos" | jq length)
114+
115+ # Initialize an empty string for paths to be outputted
116+ repo_paths_output=""
117+
118+ for i in $(seq 0 $((repo_count-1))); do
119+ name=$(echo "$repos" | jq -r ".[$i].name")
120+ url=$(echo "$repos" | jq -r ".[$i].url")
121+ ref=$(echo "$repos" | jq -r ".[$i].version") # This can be a branch, tag, or commit hash
122+ path=$(echo "$repos" | jq -r ".[$i].path") # e.g., "repos/score_baselibs"
123+
124+ echo "Checking out $name ($ref) to $path"
125+
126+ # Create the parent directory if it doesn't exist
127+ mkdir -p "$(dirname "$path")"
128+
129+ # Check if 'ref' looks like a commit hash (e.g., 40 hex characters)
130+ # This is a heuristic; a more robust check might involve fetching refs first.
131+ if [[ "$ref" =~ ^[0-9a-fA-F]{40}$ ]]; then
132+ echo " Detected commit hash. Cloning and then checking out."
133+ git clone "$url" "$path"
134+ (cd "$path" && git checkout "$ref")
135+ else
136+ echo " Detected branch/tag. Cloning with --branch."
137+ git clone --depth 1 --branch "$ref" "$url" "$path"
138+ fi
139+
140+ # Append the path to the list, separated by commas
141+ if [ -z "$repo_paths_output" ]; then
142+ repo_paths_output="$path"
143+ else
144+ repo_paths_output="$repo_paths_output,$path"
145+ fi
146+ done
147+
148+ # Output all paths as a single variable
149+ echo "repo_paths=$repo_paths_output" >> $GITHUB_OUTPUT
150+
151+ - name : Initialize CodeQL for all repositories
152+ uses : github/codeql-action/init@v4
153+ with :
154+ languages : cpp
155+ build-mode : none
156+ packs : codeql/misra-cpp-coding-standards
157+ config-file : ./.github/codeql/codeql-config.yml
158+
159+ - name : Perform CodeQL Analysis
160+ uses : github/codeql-action/analyze@v4
161+ with :
162+ upload-database : false # Don't upload databases for each repo
163+ output : sarif-results/
164+ category : " multi-repo-scan"
165+
166+ - name : Recategorize Guidelines
167+ if : always()
168+ run : |
169+ RECATEGORIZE_SCRIPT="codeql-coding-standards-repo/scripts/guideline_recategorization/recategorize.py"
170+ CODING_STANDARDS_CONFIG="./.github/codeql/coding-standards.yml"
171+
172+ CODING_STANDARDS_SCHEMA="codeql-coding-standards-repo/schemas/coding-standards-schema-1.0.0.json"
173+ SARIF_SCHEMA="codeql-coding-standards-repo/schemas/sarif-schema-2.1.0.json"
174+
175+
176+ SARIF_FILE="sarif-results/cpp.sarif"
177+
178+ mkdir -p sarif-results-recategorized
179+ echo "Processing $SARIF_FILE for recategorization..."
180+ python3 "$RECATEGORIZE_SCRIPT" \
181+ --coding-standards-schema-file "$CODING_STANDARDS_SCHEMA" \
182+ --sarif-schema-file "$SARIF_SCHEMA" \
183+ "$CODING_STANDARDS_CONFIG" \
184+ "$SARIF_FILE" \
185+ "sarif-results-recategorized/$(basename "$SARIF_FILE")"
186+
187+ rm "$SARIF_FILE"
188+ mv "sarif-results-recategorized/$(basename "$SARIF_FILE")" "$SARIF_FILE"
189+
190+ - name : Generate HTML Report from SARIF
191+ run : |
192+ SARIF_FILE="sarif-results/cpp.sarif"
193+ sarif html "$SARIF_FILE" --output codeql-report.html
194+
195+ - name : Upload SARIF results as artifact
196+ uses : actions/upload-artifact@v4
197+ with :
198+ name : codeql-sarif-results
199+ path : sarif-results/
200+
201+
202+ - name : Upload HTML Report as artifact
203+ uses : actions/upload-artifact@v4
204+ with :
205+ name : codeql-html-report
206+ path : codeql-report.html
0 commit comments