1 | # This workflow runs CodeQL against the repository.
|
---|
2 | #
|
---|
3 | # Results are uploaded to GitHub Code Scanning.
|
---|
4 | #
|
---|
5 | # Due to a known issue with the CodeQL extractor when building the edk2
|
---|
6 | # codebase on Linux systems, only Windows agents are used for build with
|
---|
7 | # the VS toolchain.
|
---|
8 | #
|
---|
9 | # Copyright (c) Microsoft Corporation.
|
---|
10 | # SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
11 |
|
---|
12 | name: "CodeQL"
|
---|
13 |
|
---|
14 | on:
|
---|
15 | push:
|
---|
16 | branches:
|
---|
17 | - master
|
---|
18 | pull_request:
|
---|
19 | branches:
|
---|
20 | - master
|
---|
21 | paths-ignore:
|
---|
22 | - '!**.c'
|
---|
23 | - '!**.h'
|
---|
24 |
|
---|
25 | jobs:
|
---|
26 | analyze:
|
---|
27 | name: Analyze
|
---|
28 | runs-on: windows-2019
|
---|
29 | permissions:
|
---|
30 | actions: read
|
---|
31 | contents: read
|
---|
32 | security-events: write
|
---|
33 |
|
---|
34 | strategy:
|
---|
35 | fail-fast: false
|
---|
36 | matrix:
|
---|
37 | include:
|
---|
38 | - Package: "ArmPkg"
|
---|
39 | ArchList: "IA32,X64"
|
---|
40 | - Package: "CryptoPkg"
|
---|
41 | ArchList: "IA32"
|
---|
42 | - Package: "CryptoPkg"
|
---|
43 | ArchList: "X64"
|
---|
44 | - Package: "DynamicTablesPkg"
|
---|
45 | ArchList: "IA32,X64"
|
---|
46 | - Package: "FatPkg"
|
---|
47 | ArchList: "IA32,X64"
|
---|
48 | - Package: "FmpDevicePkg"
|
---|
49 | ArchList: "IA32,X64"
|
---|
50 | - Package: "IntelFsp2Pkg"
|
---|
51 | ArchList: "IA32,X64"
|
---|
52 | - Package: "IntelFsp2WrapperPkg"
|
---|
53 | ArchList: "IA32,X64"
|
---|
54 | - Package: "MdeModulePkg"
|
---|
55 | ArchList: "IA32"
|
---|
56 | - Package: "MdeModulePkg"
|
---|
57 | ArchList: "X64"
|
---|
58 | - Package: "MdePkg"
|
---|
59 | ArchList: "IA32,X64"
|
---|
60 | - Package: "PcAtChipsetPkg"
|
---|
61 | ArchList: "IA32,X64"
|
---|
62 | - Package: "PrmPkg"
|
---|
63 | ArchList: "IA32,X64"
|
---|
64 | - Package: "SecurityPkg"
|
---|
65 | ArchList: "IA32,X64"
|
---|
66 | - Package: "ShellPkg"
|
---|
67 | ArchList: "IA32,X64"
|
---|
68 | - Package: "SourceLevelDebugPkg"
|
---|
69 | ArchList: "IA32,X64"
|
---|
70 | - Package: "StandaloneMmPkg"
|
---|
71 | ArchList: "IA32,X64"
|
---|
72 | - Package: "UefiCpuPkg"
|
---|
73 | ArchList: "IA32,X64"
|
---|
74 | - Package: "UnitTestFrameworkPkg"
|
---|
75 | ArchList: "IA32,X64"
|
---|
76 |
|
---|
77 | steps:
|
---|
78 | - name: Checkout repository
|
---|
79 | uses: actions/checkout@v4
|
---|
80 |
|
---|
81 | - name: Install Python
|
---|
82 | uses: actions/setup-python@v5
|
---|
83 | with:
|
---|
84 | python-version: '3.11'
|
---|
85 | cache: 'pip'
|
---|
86 | cache-dependency-path: 'pip-requirements.txt'
|
---|
87 |
|
---|
88 | - name: Use Git Long Paths on Windows
|
---|
89 | if: runner.os == 'Windows'
|
---|
90 | shell: pwsh
|
---|
91 | run: |
|
---|
92 | git config --system core.longpaths true
|
---|
93 |
|
---|
94 | - name: Install/Upgrade pip Modules
|
---|
95 | run: pip install -r pip-requirements.txt --upgrade requests sarif-tools
|
---|
96 |
|
---|
97 | - name: Determine CI Settings File Supported Operations
|
---|
98 | id: get_ci_file_operations
|
---|
99 | shell: python
|
---|
100 | run: |
|
---|
101 | import importlib
|
---|
102 | import os
|
---|
103 | import sys
|
---|
104 | from pathlib import Path
|
---|
105 | from edk2toolext.invocables.edk2_ci_setup import CiSetupSettingsManager
|
---|
106 | from edk2toolext.invocables.edk2_setup import SetupSettingsManager
|
---|
107 |
|
---|
108 | # Find the repo CI Settings file
|
---|
109 | ci_settings_file = list(Path(os.environ['GITHUB_WORKSPACE']).rglob('.pytool/CISettings.py'))
|
---|
110 |
|
---|
111 | # Note: At this point, submodules have not been pulled, only one CI Settings file should exist
|
---|
112 | if len(ci_settings_file) != 1 or not ci_settings_file[0].is_file():
|
---|
113 | print("::error title=Workspace Error!::Failed to find CI Settings file!")
|
---|
114 | sys.exit(1)
|
---|
115 |
|
---|
116 | ci_settings_file = ci_settings_file[0]
|
---|
117 |
|
---|
118 | # Try Finding the Settings class in the file
|
---|
119 | module_name = 'ci_settings'
|
---|
120 |
|
---|
121 | spec = importlib.util.spec_from_file_location(module_name, ci_settings_file)
|
---|
122 | module = importlib.util.module_from_spec(spec)
|
---|
123 | spec.loader.exec_module(module)
|
---|
124 |
|
---|
125 | try:
|
---|
126 | settings = getattr(module, 'Settings')
|
---|
127 | except AttributeError:
|
---|
128 | print("::error title=Workspace Error!::Failed to find Settings class in CI Settings file!")
|
---|
129 | sys.exit(1)
|
---|
130 |
|
---|
131 | # Determine Which Operations Are Supported by the Settings Class
|
---|
132 | ci_setup_supported = issubclass(settings, CiSetupSettingsManager)
|
---|
133 | setup_supported = issubclass(settings, SetupSettingsManager)
|
---|
134 |
|
---|
135 | with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
---|
136 | print(f'ci_setup_supported={str(ci_setup_supported).lower()}', file=fh)
|
---|
137 | print(f'setup_supported={str(setup_supported).lower()}', file=fh)
|
---|
138 |
|
---|
139 | - name: Convert Arch to Log Format
|
---|
140 | id: convert_arch_hyphen
|
---|
141 | env:
|
---|
142 | ARCH_LIST: ${{ matrix.ArchList }}
|
---|
143 | shell: python
|
---|
144 | run: |
|
---|
145 | import os
|
---|
146 |
|
---|
147 | with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
---|
148 | print(f'arch_list={os.environ["ARCH_LIST"].replace(",", "-")}', file=fh)
|
---|
149 |
|
---|
150 | - name: Setup
|
---|
151 | if: steps.get_ci_file_operations.outputs.setup_supported == 'true'
|
---|
152 | run: stuart_setup -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
|
---|
153 |
|
---|
154 | - name: Upload Setup Log As An Artifact
|
---|
155 | uses: actions/upload-artifact@v4
|
---|
156 | if: (success() || failure()) && steps.get_ci_file_operations.outputs.setup_supported == 'true'
|
---|
157 | with:
|
---|
158 | name: ${{ matrix.Package }}-${{ steps.convert_arch_hyphen.outputs.arch_list }}-Setup-Log
|
---|
159 | path: |
|
---|
160 | **/SETUPLOG.txt
|
---|
161 | retention-days: 7
|
---|
162 | if-no-files-found: ignore
|
---|
163 |
|
---|
164 | - name: CI Setup
|
---|
165 | if: steps.get_ci_file_operations.outputs.ci_setup_supported == 'true'
|
---|
166 | run: stuart_ci_setup -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
|
---|
167 |
|
---|
168 | - name: Upload CI Setup Log As An Artifact
|
---|
169 | uses: actions/upload-artifact@v4
|
---|
170 | if: (success() || failure()) && steps.get_ci_file_operations.outputs.ci_setup_supported == 'true'
|
---|
171 | with:
|
---|
172 | name: ${{ matrix.Package }}-${{ steps.convert_arch_hyphen.outputs.arch_list }}-CI-Setup-Log
|
---|
173 | path: |
|
---|
174 | **/CISETUP.txt
|
---|
175 | retention-days: 7
|
---|
176 | if-no-files-found: ignore
|
---|
177 |
|
---|
178 | - name: Update
|
---|
179 | run: stuart_update -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
|
---|
180 |
|
---|
181 | - name: Upload Update Log As An Artifact
|
---|
182 | uses: actions/upload-artifact@v4
|
---|
183 | if: success() || failure()
|
---|
184 | with:
|
---|
185 | name: ${{ matrix.Package }}-${{ steps.convert_arch_hyphen.outputs.arch_list }}-Update-Log
|
---|
186 | path: |
|
---|
187 | **/UPDATE_LOG.txt
|
---|
188 | retention-days: 7
|
---|
189 | if-no-files-found: ignore
|
---|
190 |
|
---|
191 | - name: Build Tools From Source
|
---|
192 | run: python BaseTools/Edk2ToolsBuild.py -t VS2019
|
---|
193 |
|
---|
194 | - name: Find CodeQL Plugin Directory
|
---|
195 | id: find_dir
|
---|
196 | shell: python
|
---|
197 | run: |
|
---|
198 | import os
|
---|
199 | import sys
|
---|
200 | from pathlib import Path
|
---|
201 |
|
---|
202 | # Find the plugin directory that contains the CodeQL plugin
|
---|
203 | plugin_dir = list(Path(os.environ['GITHUB_WORKSPACE']).rglob('BaseTools/Plugin/CodeQL'))
|
---|
204 |
|
---|
205 | # This should only be found once
|
---|
206 | if len(plugin_dir) == 1:
|
---|
207 | plugin_dir = str(plugin_dir[0])
|
---|
208 |
|
---|
209 | with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
---|
210 | print(f'codeql_plugin_dir={plugin_dir}', file=fh)
|
---|
211 | else:
|
---|
212 | print("::error title=Workspace Error!::Failed to find CodeQL plugin directory!")
|
---|
213 | sys.exit(1)
|
---|
214 |
|
---|
215 | - name: Get CodeQL CLI Cache Data
|
---|
216 | id: cache_key_gen
|
---|
217 | env:
|
---|
218 | CODEQL_PLUGIN_DIR: ${{ steps.find_dir.outputs.codeql_plugin_dir }}
|
---|
219 | shell: python
|
---|
220 | run: |
|
---|
221 | import os
|
---|
222 | import yaml
|
---|
223 |
|
---|
224 | codeql_cli_ext_dep_name = 'codeqlcli_windows_ext_dep'
|
---|
225 | codeql_plugin_file = os.path.join(os.environ['CODEQL_PLUGIN_DIR'], codeql_cli_ext_dep_name + '.yaml')
|
---|
226 |
|
---|
227 | with open (codeql_plugin_file) as pf:
|
---|
228 | codeql_cli_ext_dep = yaml.safe_load(pf)
|
---|
229 |
|
---|
230 | cache_key_name = codeql_cli_ext_dep['name']
|
---|
231 | cache_key_version = codeql_cli_ext_dep['version']
|
---|
232 | cache_key = f'{cache_key_name}-{cache_key_version}'
|
---|
233 |
|
---|
234 | codeql_plugin_cli_ext_dep_dir = os.path.join(os.environ['CODEQL_PLUGIN_DIR'], codeql_cli_ext_dep['name'].strip() + '_extdep')
|
---|
235 |
|
---|
236 | with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
---|
237 | print(f'codeql_cli_cache_key={cache_key}', file=fh)
|
---|
238 | print(f'codeql_cli_ext_dep_dir={codeql_plugin_cli_ext_dep_dir}', file=fh)
|
---|
239 |
|
---|
240 | - name: Attempt to Load CodeQL CLI From Cache
|
---|
241 | id: codeqlcli_cache
|
---|
242 | uses: actions/cache@v4
|
---|
243 | with:
|
---|
244 | path: ${{ steps.cache_key_gen.outputs.codeql_cli_ext_dep_dir }}
|
---|
245 | key: ${{ steps.cache_key_gen.outputs.codeql_cli_cache_key }}
|
---|
246 |
|
---|
247 | - name: Download CodeQL CLI
|
---|
248 | if: steps.codeqlcli_cache.outputs.cache-hit != 'true'
|
---|
249 | run: stuart_update -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019 --codeql
|
---|
250 |
|
---|
251 | - name: Remove CI Plugins Irrelevant to CodeQL
|
---|
252 | shell: python
|
---|
253 | env:
|
---|
254 | CODEQL_PLUGIN_DIR: ${{ steps.find_dir.outputs.codeql_plugin_dir }}
|
---|
255 | run: |
|
---|
256 | import os
|
---|
257 | import shutil
|
---|
258 | from pathlib import Path
|
---|
259 |
|
---|
260 | # Only these two plugins are needed for CodeQL
|
---|
261 | plugins_to_keep = ['CompilerPlugin']
|
---|
262 |
|
---|
263 | plugin_dir = Path('.pytool/Plugin').absolute()
|
---|
264 | if plugin_dir.is_dir():
|
---|
265 | for dir in plugin_dir.iterdir():
|
---|
266 | if str(dir.stem) not in plugins_to_keep:
|
---|
267 | shutil.rmtree(str(dir.absolute()), ignore_errors=True)
|
---|
268 |
|
---|
269 | - name: CI Build
|
---|
270 | env:
|
---|
271 | STUART_CODEQL_PATH: ${{ steps.cache_key_gen.outputs.codeql_cli_ext_dep_dir }}
|
---|
272 | run: stuart_ci_build -c .pytool/CISettings.py -t DEBUG -p ${{ matrix.Package }} -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019 --codeql
|
---|
273 |
|
---|
274 | - name: Build Cleanup
|
---|
275 | id: build_cleanup
|
---|
276 | shell: python
|
---|
277 | run: |
|
---|
278 | import os
|
---|
279 | import shutil
|
---|
280 | from pathlib import Path
|
---|
281 |
|
---|
282 | dirs_to_delete = ['ia32', 'x64', 'arm', 'aarch64']
|
---|
283 |
|
---|
284 | def delete_dirs(path: Path):
|
---|
285 | if path.exists() and path.is_dir():
|
---|
286 | if path.name.lower() in dirs_to_delete:
|
---|
287 | print(f'Removed {str(path)}')
|
---|
288 | shutil.rmtree(path)
|
---|
289 | return
|
---|
290 |
|
---|
291 | for child_dir in path.iterdir():
|
---|
292 | delete_dirs(child_dir)
|
---|
293 |
|
---|
294 | build_path = Path(os.environ['GITHUB_WORKSPACE'], 'Build')
|
---|
295 | delete_dirs(build_path)
|
---|
296 |
|
---|
297 | - name: Upload Build Logs As An Artifact
|
---|
298 | uses: actions/upload-artifact@v4
|
---|
299 | if: success() || failure()
|
---|
300 | with:
|
---|
301 | name: ${{ matrix.Package }}-${{ steps.convert_arch_hyphen.outputs.arch_list }}-Build-Logs
|
---|
302 | path: |
|
---|
303 | **/BUILD_REPORT.TXT
|
---|
304 | **/OVERRIDELOG.TXT
|
---|
305 | **/BUILDLOG_*.md
|
---|
306 | **/BUILDLOG_*.txt
|
---|
307 | **/CI_*.md
|
---|
308 | **/CI_*.txt
|
---|
309 | retention-days: 7
|
---|
310 | if-no-files-found: ignore
|
---|
311 |
|
---|
312 | - name: Prepare Env Data for CodeQL Upload
|
---|
313 | id: env_data
|
---|
314 | env:
|
---|
315 | PACKAGE_NAME: ${{ matrix.Package }}
|
---|
316 | shell: python
|
---|
317 | run: |
|
---|
318 | import logging
|
---|
319 | import os
|
---|
320 | from edk2toollib.utility_functions import RunCmd
|
---|
321 | from io import StringIO
|
---|
322 | from pathlib import Path
|
---|
323 |
|
---|
324 | package = os.environ['PACKAGE_NAME'].strip().lower()
|
---|
325 | directory_name = 'codeql-analysis-' + package + '-debug'
|
---|
326 | file_name = 'codeql-db-' + package + '-debug-0.sarif'
|
---|
327 | sarif_path = Path('Build', directory_name, file_name)
|
---|
328 |
|
---|
329 | with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
---|
330 | if sarif_path.is_file():
|
---|
331 | emacs_file_path = sarif_path.with_name(sarif_path.stem + "-emacs.txt")
|
---|
332 | out_stream_buffer = StringIO()
|
---|
333 | exit_code = RunCmd("sarif", f"emacs {sarif_path} --output {emacs_file_path} --no-autotrim",
|
---|
334 | outstream=out_stream_buffer,
|
---|
335 | logging_level=logging.NOTSET)
|
---|
336 | print(f'upload_sarif_file=true', file=fh)
|
---|
337 | print(f'emacs_file_path={emacs_file_path}', file=fh)
|
---|
338 | print(f'sarif_file_path={sarif_path}', file=fh)
|
---|
339 | else:
|
---|
340 | print(f'upload_sarif_file=false', file=fh)
|
---|
341 |
|
---|
342 | - name: Upload CodeQL Results (SARIF) As An Artifact
|
---|
343 | uses: actions/upload-artifact@v4
|
---|
344 | if: steps.env_data.outputs.upload_sarif_file == 'true'
|
---|
345 | with:
|
---|
346 | name: ${{ matrix.Package }}-${{ steps.convert_arch_hyphen.outputs.arch_list }}-CodeQL-SARIF
|
---|
347 | path: |
|
---|
348 | ${{ steps.env_data.outputs.emacs_file_path }}
|
---|
349 | ${{ steps.env_data.outputs.sarif_file_path }}
|
---|
350 | retention-days: 14
|
---|
351 | if-no-files-found: warn
|
---|
352 |
|
---|
353 | - name: Upload CodeQL Results (SARIF) To GitHub Code Scanning
|
---|
354 | uses: github/codeql-action/upload-sarif@v3
|
---|
355 | if: steps.env_data.outputs.upload_sarif_file == 'true'
|
---|
356 | with:
|
---|
357 | # Path to SARIF file relative to the root of the repository.
|
---|
358 | sarif_file: ${{ steps.env_data.outputs.sarif_file_path }}
|
---|
359 | # Optional category for the results. Used to differentiate multiple results for one commit.
|
---|
360 | # Each package is a separate category.
|
---|
361 | category: ${{ matrix.Package }}
|
---|