88 branches :
99 - main
1010
11+ # Cancel in-progress runs for the same PR/branch
12+ concurrency :
13+ group : ${{ github.workflow }}-${{ github.ref }}
14+ cancel-in-progress : true
15+
16+ # Least-privilege permissions
17+ permissions :
18+ contents : read
19+ actions : write # Required for actions/cache@v4 to save/restore cache
20+
1121jobs :
12- matrix-tests :
22+ # Fast-running lint job to catch formatting issues early
23+ lint :
1324 runs-on : ubuntu-24.04
14- name : Test on ${{ matrix.toolchain }} toolchain
25+ name : Code Quality Checks
26+ timeout-minutes : 10
1527
16- strategy :
17- fail-fast : false
18- matrix :
19- toolchain : [gnu, llvm]
28+ env :
29+ CLANG_FORMAT_VERSION : 18
2030
2131 steps :
2232 - name : Checkout
23- uses : actions/checkout@v4
33+ uses : actions/checkout@v5
2434
25- - name : Install base dependencies
35+ - name : Install linting tools
2636 run : |
2737 sudo apt-get update
28- sudo apt-get install -y build-essential qemu-system-riscv32 wget clang-format-18 shfmt
38+ sudo apt-get install -y --no-install-recommends clang-format-${{ env.CLANG_FORMAT_VERSION }} shfmt
2939
3040 - name : Check code formatting
3141 run : .ci/check-format.sh
3242
3343 - name : Check newline at end of files
3444 run : .ci/check-newline.sh
3545
46+ # Build and test matrix - runs in parallel after lint passes
47+ # NOTE: LLVM toolchain performs build-only validation (no runtime tests)
48+ # to verify cross-toolchain compilation compatibility. GNU toolchain
49+ # runs the full test suite including application and functional tests.
50+ matrix-tests :
51+ runs-on : ubuntu-24.04
52+ name : Test on ${{ matrix.toolchain }} toolchain
53+ needs : lint
54+ timeout-minutes : 30
55+
56+ strategy :
57+ fail-fast : false
58+ matrix :
59+ toolchain : [gnu, llvm]
60+
61+ steps :
62+ - name : Checkout
63+ uses : actions/checkout@v5
64+
65+ - name : Cache toolchain
66+ uses : actions/cache@v4
67+ id : cache-toolchain
68+ with :
69+ path : riscv
70+ key : ${{ runner.os }}-${{ matrix.toolchain }}-toolchain-${{ hashFiles('.ci/setup-toolchain.sh') }}
71+ restore-keys : |
72+ ${{ runner.os }}-${{ matrix.toolchain }}-toolchain-
73+
74+ - name : Install build dependencies
75+ run : |
76+ sudo apt-get update
77+ sudo apt-get install -y --no-install-recommends build-essential qemu-system-riscv32 wget
78+
3679 - name : Setup ${{ matrix.toolchain }} toolchain
80+ if : steps.cache-toolchain.outputs.cache-hit != 'true'
3781 run : .ci/setup-toolchain.sh ${{ matrix.toolchain }}
3882
83+ - name : Configure toolchain environment
84+ if : steps.cache-toolchain.outputs.cache-hit == 'true'
85+ run : |
86+ echo "$PWD/riscv/bin" >> "$GITHUB_PATH"
87+ echo "CROSS_COMPILE=riscv32-unknown-elf-" >> "$GITHUB_ENV"
88+ echo "TOOLCHAIN_TYPE=${{ matrix.toolchain }}" >> "$GITHUB_ENV"
89+
3990 - name : Verify toolchain installation
4091 run : |
4192 if [ "${{ matrix.toolchain }}" = "gnu" ]; then
49100
50101 - name : Build Kernel
51102 run : |
103+ set -euo pipefail
52104 make clean
53- make
105+ make -j$(nproc)
54106 env :
55107 TOOLCHAIN_TYPE : ${{ matrix.toolchain }}
56108
59111 continue-on-error : true
60112 if : matrix.toolchain == 'gnu'
61113 run : |
114+ set -euo pipefail
62115 output=$(.ci/run-app-tests.sh 2>&1) || true
63116 echo "TEST_OUTPUT<<EOF" >> $GITHUB_OUTPUT
64117 echo "$output" >> $GITHUB_OUTPUT
71124 continue-on-error : true
72125 if : matrix.toolchain == 'gnu'
73126 run : |
127+ set -euo pipefail
74128 output=$(.ci/run-functional-tests.sh 2>&1) || true
75129 echo "FUNCTIONAL_TEST_OUTPUT<<EOF" >> $GITHUB_OUTPUT
76130 echo "$output" >> $GITHUB_OUTPUT
81135 - name : Collect Test Data
82136 if : always()
83137 run : |
138+ set -euo pipefail
84139 if [ "${{ matrix.toolchain }}" = "llvm" ]; then
85140 # LLVM: Build-only validation, skip tests
86141 mkdir -p test-results
@@ -103,7 +158,7 @@ jobs:
103158 echo "mutex:mutual_exclusion=skipped" >> test-results/functional_criteria_data
104159 echo "mutex:data_consistency=skipped" >> test-results/functional_criteria_data
105160 echo "mutex:overall=skipped" >> test-results/functional_criteria_data
106- echo "semaphore:all_tests_passed! =skipped" >> test-results/functional_criteria_data
161+ echo "semaphore:overall =skipped" >> test-results/functional_criteria_data
107162
108163 echo "LLVM toolchain: Build validation only (tests skipped)"
109164 else
@@ -117,13 +172,18 @@ jobs:
117172 with :
118173 name : test-results-${{ matrix.toolchain }}
119174 path : test-results/
120- retention-days : 1
175+ retention-days : 3
176+ if-no-files-found : warn
121177
122178 # Comprehensive test summary with detailed reporting
123179 test-summary :
124180 runs-on : ubuntu-24.04
125- needs : matrix-tests
181+ needs : [lint, matrix-tests]
126182 if : always()
183+ timeout-minutes : 15
184+ permissions :
185+ contents : read
186+ pull-requests : write
127187
128188 steps :
129189 - name : Checkout
@@ -136,41 +196,66 @@ jobs:
136196 path : all-test-results/
137197
138198 - name : Generate Test Summary
199+ id : generate_summary
139200 continue-on-error : true
140201 run : |
202+ echo "Aggregating test results..."
141203 .ci/ci-tools.sh aggregate all-test-results test-summary.toml
142- cat test-summary.toml
204+
205+ if [ -f test-summary.toml ]; then
206+ echo "summary_generated=true" >> $GITHUB_OUTPUT
207+ echo "Test Summary:"
208+ cat test-summary.toml
209+ else
210+ echo "summary_generated=false" >> $GITHUB_OUTPUT
211+ echo "⚠️ Warning: test-summary.toml not generated"
212+ fi
143213
144214 - name : Upload Test Summary
145- if : always()
215+ if : always() && steps.generate_summary.outputs.summary_generated == 'true'
146216 uses : actions/upload-artifact@v4
147217 with :
148218 name : test-summary
149219 path : test-summary.toml
150220 retention-days : 30
221+ if-no-files-found : error
151222
152223 - name : Comment PR with Formatted Summary
153- if : always() && github.event_name == 'pull_request'
224+ if : always() && github.event_name == 'pull_request' && steps.generate_summary.outputs.summary_generated == 'true'
154225 continue-on-error : true
155226 run : |
227+ echo "Posting summary to PR #${{ github.event.number }}..."
156228 .ci/ci-tools.sh post-comment test-summary.toml ${{ github.event.number }}
157229 env :
158230 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
159231
160232 - name : Final Status Check
161233 run : |
234+ set -euo pipefail
235+ echo "=== Final CI Status Check ==="
236+
162237 if [ ! -f test-summary.toml ]; then
163- echo "Error: test-summary.toml not found"
238+ echo "❌ Error: test-summary.toml not found"
239+ echo "CI infrastructure issue - check test aggregation step"
164240 exit 1
165241 fi
166242
167243 overall_status=$(grep -A 1 '^\[summary\]' test-summary.toml | grep 'status =' | cut -d'"' -f2)
168244 echo "Overall test status: $overall_status"
169245
246+ # Extract failure details if available
247+ if [ "$overall_status" != "passed" ]; then
248+ echo ""
249+ echo "=== Failure Details ==="
250+ grep -E '(failed|error|skipped)' test-summary.toml || true
251+ fi
252+
170253 if [ "$overall_status" = "passed" ]; then
171- echo "✅ All tests passed"
254+ echo ""
255+ echo "✅ All tests passed successfully"
172256 exit 0
173257 else
174- echo "❌ Tests failed"
258+ echo ""
259+ echo "❌ Tests failed - see details above"
175260 exit 1
176261 fi
0 commit comments