Skip to content

Commit 1384ce4

Browse files
makubackimergify[bot]
authored andcommitted
.github/workflows/codeql.yml: Add CodeQL workflow
Adds a workflow to run CodeQL against all packages built in .pytool/CISettings.py. The following is done: 1. Determine which packages to build against. Those that support are managed by .pytool/CISettings.py will be selected. For each package: 2. Determine how to interact with the package. Such as whether `stuart_ci_setup` or `stuart_setup` should be used. 3. Perform supported Stuart steps for setup and update. 4. Discover the CodeQL plugin directory in the repo. 5. Attempt to load the CodeQL CLI specific to the host OS from a GitHub cache. 6. Perform the build. 7. Clean up some files after build to improve robustness. 8. Upload the CodeQL results (generated SARIF file) to GitHub Code Scanning. The results will be associated with the trigger of the workflow. After each step that can upload logs such as the setup, update, and build steps the logs are uploaded as an artifact to the workflow run. This allows easy debugging in case there's an error in the step. The SARIF file is also uploaded to the workflow run so it can be downloaded and analyzed. Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Sean Brogan <sean.brogan@microsoft.com> Acked-by: Laszlo Ersek <lersek@redhat.com> Acked-by: Michael D Kinney <michael.d.kinney@intel.com>
1 parent 2976301 commit 1384ce4

File tree

1 file changed

+338
-0
lines changed

1 file changed

+338
-0
lines changed

.github/workflows/codeql.yml

Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
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@v4
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
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: Setup
140+
if: steps.get_ci_file_operations.outputs.setup_supported == 'true'
141+
run: stuart_setup -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
142+
143+
- name: Upload Setup Log As An Artifact
144+
uses: actions/upload-artifact@v3
145+
if: (success() || failure()) && steps.get_ci_file_operations.outputs.setup_supported == 'true'
146+
with:
147+
name: ${{ matrix.Package }}-Logs
148+
path: |
149+
**/SETUPLOG.txt
150+
retention-days: 7
151+
if-no-files-found: ignore
152+
153+
- name: CI Setup
154+
if: steps.get_ci_file_operations.outputs.ci_setup_supported == 'true'
155+
run: stuart_ci_setup -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
156+
157+
- name: Upload CI Setup Log As An Artifact
158+
uses: actions/upload-artifact@v3
159+
if: (success() || failure()) && steps.get_ci_file_operations.outputs.ci_setup_supported == 'true'
160+
with:
161+
name: ${{ matrix.Package }}-Logs
162+
path: |
163+
**/CISETUP.txt
164+
retention-days: 7
165+
if-no-files-found: ignore
166+
167+
- name: Update
168+
run: stuart_update -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
169+
170+
- name: Upload Update Log As An Artifact
171+
uses: actions/upload-artifact@v3
172+
if: success() || failure()
173+
with:
174+
name: ${{ matrix.Package }}-Logs
175+
path: |
176+
**/UPDATE_LOG.txt
177+
retention-days: 7
178+
if-no-files-found: ignore
179+
180+
- name: Build Tools From Source
181+
run: python BaseTools/Edk2ToolsBuild.py -t VS2019
182+
183+
- name: Find CodeQL Plugin Directory
184+
id: find_dir
185+
shell: python
186+
run: |
187+
import os
188+
import sys
189+
from pathlib import Path
190+
191+
# Find the plugin directory that contains the CodeQL plugin
192+
plugin_dir = list(Path(os.environ['GITHUB_WORKSPACE']).rglob('BaseTools/Plugin/CodeQL'))
193+
194+
# This should only be found once
195+
if len(plugin_dir) == 1:
196+
plugin_dir = str(plugin_dir[0])
197+
198+
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
199+
print(f'codeql_plugin_dir={plugin_dir}', file=fh)
200+
else:
201+
print("::error title=Workspace Error!::Failed to find CodeQL plugin directory!")
202+
sys.exit(1)
203+
204+
- name: Get CodeQL CLI Cache Data
205+
id: cache_key_gen
206+
env:
207+
CODEQL_PLUGIN_DIR: ${{ steps.find_dir.outputs.codeql_plugin_dir }}
208+
shell: python
209+
run: |
210+
import os
211+
import yaml
212+
213+
codeql_cli_ext_dep_name = 'codeqlcli_windows_ext_dep'
214+
codeql_plugin_file = os.path.join(os.environ['CODEQL_PLUGIN_DIR'], codeql_cli_ext_dep_name + '.yaml')
215+
216+
with open (codeql_plugin_file) as pf:
217+
codeql_cli_ext_dep = yaml.safe_load(pf)
218+
219+
cache_key_name = codeql_cli_ext_dep['name']
220+
cache_key_version = codeql_cli_ext_dep['version']
221+
cache_key = f'{cache_key_name}-{cache_key_version}'
222+
223+
codeql_plugin_cli_ext_dep_dir = os.path.join(os.environ['CODEQL_PLUGIN_DIR'], codeql_cli_ext_dep['name'].strip() + '_extdep')
224+
225+
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
226+
print(f'codeql_cli_cache_key={cache_key}', file=fh)
227+
print(f'codeql_cli_ext_dep_dir={codeql_plugin_cli_ext_dep_dir}', file=fh)
228+
229+
- name: Attempt to Load CodeQL CLI From Cache
230+
id: codeqlcli_cache
231+
uses: actions/cache@v3
232+
with:
233+
path: ${{ steps.cache_key_gen.outputs.codeql_cli_ext_dep_dir }}
234+
key: ${{ steps.cache_key_gen.outputs.codeql_cli_cache_key }}
235+
236+
- name: Download CodeQL CLI
237+
if: steps.codeqlcli_cache.outputs.cache-hit != 'true'
238+
run: stuart_update -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019 --codeql
239+
240+
- name: Remove CI Plugins Irrelevant to CodeQL
241+
shell: python
242+
env:
243+
CODEQL_PLUGIN_DIR: ${{ steps.find_dir.outputs.codeql_plugin_dir }}
244+
run: |
245+
import os
246+
import shutil
247+
from pathlib import Path
248+
249+
# Only these two plugins are needed for CodeQL
250+
plugins_to_keep = ['CompilerPlugin']
251+
252+
plugin_dir = Path('.pytool/Plugin').absolute()
253+
if plugin_dir.is_dir():
254+
for dir in plugin_dir.iterdir():
255+
if str(dir.stem) not in plugins_to_keep:
256+
shutil.rmtree(str(dir.absolute()), ignore_errors=True)
257+
258+
- name: CI Build
259+
env:
260+
STUART_CODEQL_PATH: ${{ steps.cache_key_gen.outputs.codeql_cli_ext_dep_dir }}
261+
run: stuart_ci_build -c .pytool/CISettings.py -t DEBUG -p ${{ matrix.Package }} -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019 --codeql
262+
263+
- name: Build Cleanup
264+
id: build_cleanup
265+
shell: python
266+
run: |
267+
import os
268+
import shutil
269+
from pathlib import Path
270+
271+
dirs_to_delete = ['ia32', 'x64', 'arm', 'aarch64']
272+
273+
def delete_dirs(path: Path):
274+
if path.exists() and path.is_dir():
275+
if path.name.lower() in dirs_to_delete:
276+
print(f'Removed {str(path)}')
277+
shutil.rmtree(path)
278+
return
279+
280+
for child_dir in path.iterdir():
281+
delete_dirs(child_dir)
282+
283+
build_path = Path(os.environ['GITHUB_WORKSPACE'], 'Build')
284+
delete_dirs(build_path)
285+
286+
- name: Upload Build Logs As An Artifact
287+
uses: actions/upload-artifact@v3
288+
if: success() || failure()
289+
with:
290+
name: ${{ matrix.Package }}-Logs
291+
path: |
292+
**/BUILD_REPORT.TXT
293+
**/OVERRIDELOG.TXT
294+
**/BUILDLOG_*.md
295+
**/BUILDLOG_*.txt
296+
**/CI_*.md
297+
**/CI_*.txt
298+
retention-days: 7
299+
if-no-files-found: ignore
300+
301+
- name: Prepare Env Data for CodeQL Upload
302+
id: env_data
303+
env:
304+
PACKAGE_NAME: ${{ matrix.Package }}
305+
shell: python
306+
run: |
307+
import os
308+
309+
package = os.environ['PACKAGE_NAME'].strip().lower()
310+
directory_name = 'codeql-analysis-' + package + '-debug'
311+
file_name = 'codeql-db-' + package + '-debug-0.sarif'
312+
sarif_path = os.path.join('Build', directory_name, file_name)
313+
314+
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
315+
if os.path.isfile(sarif_path):
316+
print(f'upload_sarif_file=true', file=fh)
317+
print(f'sarif_file_path={sarif_path}', file=fh)
318+
else:
319+
print(f'upload_sarif_file=false', file=fh)
320+
321+
- name: Upload CodeQL Results (SARIF) As An Artifact
322+
uses: actions/upload-artifact@v3
323+
if: steps.env_data.outputs.upload_sarif_file == 'true'
324+
with:
325+
name: ${{ matrix.Package }}-CodeQL-SARIF
326+
path: ${{ steps.env_data.outputs.sarif_file_path }}
327+
retention-days: 14
328+
if-no-files-found: warn
329+
330+
- name: Upload CodeQL Results (SARIF) To GitHub Code Scanning
331+
uses: github/codeql-action/upload-sarif@v2
332+
if: steps.env_data.outputs.upload_sarif_file == 'true'
333+
with:
334+
# Path to SARIF file relative to the root of the repository.
335+
sarif_file: ${{ steps.env_data.outputs.sarif_file_path }}
336+
# Optional category for the results. Used to differentiate multiple results for one commit.
337+
# Each package is a separate category.
338+
category: ${{ matrix.Package }}

0 commit comments

Comments
 (0)