1+ name : Build CodeQL Packs
2+
3+ on :
4+ pull_request :
5+ branches : [ main ]
6+ workflow_dispatch :
7+
8+ jobs :
9+ compile-and-test :
10+ name : Compile and Test CodeQL Packs
11+ runs-on : ubuntu-latest
12+
13+ strategy :
14+ fail-fast : false
15+ matrix :
16+ language : [ 'common', 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
17+
18+ steps :
19+ - uses : actions/checkout@v4
20+
21+ - name : Setup CodeQL
22+ id : install-codeql
23+ uses : ./.github/actions/install-codeql
24+
25+ - name : Install CodeQL packs
26+ uses : ./.github/actions/install-codeql-packs
27+ with :
28+ cli_path : ${{ github.workspace }}/codeql_home/codeql
29+ language : ${{ matrix.language }}
30+
31+ - name : Pre-Compile Queries
32+ id : pre-compile-queries
33+ if : ${{ matrix.language != 'common' }}
34+ run : |
35+ ${{ github.workspace }}/codeql_home/codeql/codeql query compile --threads 0 ${{ matrix.language }}
36+
37+ - name : Test Queries
38+ env :
39+ RUNNER_TEMP : ${{ runner.temp }}
40+ shell : python
41+ run : |
42+ import os
43+ import sys
44+ import subprocess
45+ from pathlib import Path
46+
47+ def print_error(fmt, *args):
48+ print(f"::error::{fmt}", *args)
49+
50+ def print_error_and_fail(fmt, *args):
51+ print_error(fmt, args)
52+ sys.exit(1)
53+
54+ runner_temp = os.environ['RUNNER_TEMP']
55+
56+ if '${{ matrix.language }}' == 'common':
57+ test_root = Path('${{ github.workspace }}', 'test')
58+ else:
59+ test_root = Path('${{ github.workspace }}', '${{ matrix.language }}', 'test')
60+ print(f"Executing tests found (recursively) in the directory '{test_root}'")
61+ files_to_close = []
62+ try:
63+ # Runners have 4 cores, so split the tests into 4 "slices", and run one per thread
64+ num_slices = 4
65+ procs = []
66+
67+ for slice in range(1, num_slices+1):
68+ test_report_path = os.path.join(runner_temp, "${{ matrix.language }}", f"test_report_slice_{slice}_of_{num_slices}.json")
69+ os.makedirs(os.path.dirname(test_report_path), exist_ok=True)
70+ test_report_file = open(test_report_path, 'w')
71+ files_to_close.append(test_report_file)
72+ procs.append(subprocess.Popen(["codeql", "test", "run", "--failing-exitcode=122", f"--slice={slice}/{num_slices}", "--ram=2048", "--format=json", test_root], stdout=test_report_file, stderr=subprocess.PIPE))
73+
74+ for p in procs:
75+ _, err = p.communicate()
76+ if p.returncode != 0:
77+ if p.returncode == 122:
78+ # Failed because a test case failed, so just print the regular output.
79+ # This will allow us to proceed to validate-test-results, which will fail if
80+ # any test cases failed
81+ print(f"{err.decode()}")
82+ else:
83+ # Some more serious problem occurred, so print and fail fast
84+ print_error_and_fail(f"Failed to run tests with return code {p.returncode}\n{err.decode()}")
85+ finally:
86+ for file in files_to_close:
87+ file.close()
88+
89+ - name : Upload test results
90+ uses : actions/upload-artifact@v4
91+ with :
92+ name : ${{ matrix.language }}-test-results
93+ path : |
94+ ${{ runner.temp }}/${{ matrix.language }}/test_report_slice_*.json
95+ if-no-files-found : error
96+
97+ validate-test-results :
98+ name : Validate test results
99+ needs : compile-and-test
100+ if : ${{ always() }}
101+ runs-on : ubuntu-latest
102+ steps :
103+ - name : Check if compile-and-test job failed to complete, if so fail
104+ if : ${{ needs.compile-and-test.result == 'failure' }}
105+ uses : actions/github-script@v7
106+ with :
107+ script : |
108+ core.setFailed('Test run job failed')
109+
110+ - name : Collect test results
111+ uses : actions/download-artifact@v4
112+
113+ - name : Validate test results
114+ run : |
115+ if [[ ! -n "$(find . -name 'test_report_*' -print -quit)" ]]; then
116+ echo "No test results found"
117+ exit 0
118+ fi
119+
120+ for json_report in *-test-results/test_report_*
121+ do
122+ jq --raw-output '"PASS \(map(select(.pass == true)) | length)/\(length)'" $json_report\"" "$json_report"
123+ done
124+ FAILING_TESTS=$(jq --raw-output '.[] | select(.pass == false)' *-test-results/test_report_*.json)
125+ if [[ ! -z "$FAILING_TESTS" ]]; then
126+ echo "ERROR: The following tests failed:"
127+ echo $FAILING_TESTS | jq .
128+ exit 1
129+ fi
130+
0 commit comments