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