Skip to content

Commit 6a53110

Browse files
committed
Merge main: combine C++ and Jest/Mocha test framework support
Resolves merge conflict by integrating: - C++ test support from main (cmake, gtest, ctest) - Jest/Mocha test support from this branch - Unified aggregate-results job for all 4 frameworks - Single notification job covering pytest, Jest, Mocha, and C++
2 parents 54207ef + 93bb9b3 commit 6a53110

5 files changed

Lines changed: 1166 additions & 2025 deletions

File tree

.github/workflows/run-branch-test.yml

Lines changed: 154 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,50 @@ on:
77
description: "Target branch to compare against (e.g., main)."
88
required: true
99
type: string
10+
# Python/pytest options
1011
python-version:
1112
description: "Python version for pytest."
1213
required: false
1314
type: string
1415
default: "3.10"
16+
# Node.js options for Jest/Mocha
1517
node-version:
1618
description: "Node.js version for Jest/Mocha."
1719
required: false
1820
type: string
1921
default: "18"
22+
# C++/CMake options
23+
cmake-version:
24+
description: "CMake version for C++ tests."
25+
required: false
26+
type: string
27+
default: "3.28"
28+
cpp-compiler:
29+
description: "C++ compiler (gcc, clang). Auto-detects if empty."
30+
required: false
31+
type: string
32+
default: ""
33+
cpp-build-type:
34+
description: "CMake build type (Debug, Release, RelWithDebInfo, MinSizeRel)."
35+
required: false
36+
type: string
37+
default: "Release"
38+
cpp-build-dir:
39+
description: "Build directory for C++ projects."
40+
required: false
41+
type: string
42+
default: "build"
43+
cpp-cmake-args:
44+
description: "Additional CMake configuration arguments."
45+
required: false
46+
type: string
47+
default: ""
48+
cpp-test-args:
49+
description: "Additional CTest arguments."
50+
required: false
51+
type: string
52+
default: ""
53+
# Common options
2054
runs_on:
2155
description: "Runner label."
2256
required: false
@@ -27,6 +61,12 @@ on:
2761
required: false
2862
type: string
2963
default: ""
64+
use_target_cache:
65+
description: "Whether to use caching for target branch test results. When false, always runs fresh tests."
66+
required: false
67+
type: boolean
68+
default: false
69+
# Jest options
3070
jest-command:
3171
description: "Base command used to invoke Jest."
3272
required: false
@@ -37,6 +77,7 @@ on:
3777
required: false
3878
type: string
3979
default: ""
80+
# Mocha options
4081
mocha-command:
4182
description: "Base command used to invoke Mocha."
4283
required: false
@@ -64,6 +105,12 @@ on:
64105
regression_count:
65106
description: "Total number of regressions (all frameworks)"
66107
value: ${{ jobs.aggregate-results.outputs.regression_count }}
108+
cpp_has_regressions:
109+
description: "Whether regressions were detected (C++)"
110+
value: ${{ jobs.cpp-compare.outputs.has_regressions }}
111+
cpp_regression_count:
112+
description: "Number of regressions (C++)"
113+
value: ${{ jobs.cpp-compare.outputs.regression_count }}
67114

68115
jobs:
69116
# Detect which test frameworks are present
@@ -73,6 +120,7 @@ jobs:
73120
has_pytest: ${{ steps.detect.outputs.has_pytest }}
74121
has_jest: ${{ steps.detect.outputs.has_jest }}
75122
has_mocha: ${{ steps.detect.outputs.has_mocha }}
123+
has_cpp: ${{ steps.detect.outputs.has_cpp }}
76124
steps:
77125
- uses: actions/checkout@v4.2.2
78126
- name: Detect test frameworks
@@ -81,11 +129,30 @@ jobs:
81129
# Detect pytest
82130
if [ -f "pyproject.toml" ] || [ -f "setup.py" ] || [ -f "requirements.txt" ] || find . -name "test_*.py" -o -name "*_test.py" 2>/dev/null | head -1 | grep -q .; then
83131
echo "has_pytest=true" >> $GITHUB_OUTPUT
84-
echo "Detected: pytest"
132+
echo "Detected: pytest"
85133
else
86134
echo "has_pytest=false" >> $GITHUB_OUTPUT
87135
fi
88136
137+
# Detect C++ with CMake and tests
138+
HAS_CPP="false"
139+
if [ -f "CMakeLists.txt" ]; then
140+
# Check for test-related CMake content
141+
if grep -rqE "(enable_testing|add_test|gtest|catch|boost.*test)" CMakeLists.txt 2>/dev/null || \
142+
find . -name "CMakeLists.txt" -exec grep -lE "(enable_testing|add_test|gtest|catch)" {} \; 2>/dev/null | head -1 | grep -q .; then
143+
HAS_CPP="true"
144+
echo "✅ Detected: C++ (CMake with tests)"
145+
fi
146+
fi
147+
# Check for test source files
148+
if [ "$HAS_CPP" = "false" ]; then
149+
if find . \( -name "*_test.cpp" -o -name "*_test.cc" -o -name "test_*.cpp" -o -name "test_*.cc" \) 2>/dev/null | head -1 | grep -q .; then
150+
HAS_CPP="true"
151+
echo "✅ Detected: C++ test files"
152+
fi
153+
fi
154+
echo "has_cpp=$HAS_CPP" >> $GITHUB_OUTPUT
155+
89156
# Detect Jest
90157
HAS_JEST="false"
91158
if [ -f "package.json" ]; then
@@ -104,7 +171,7 @@ jobs:
104171
fi
105172
echo "has_jest=$HAS_JEST" >> $GITHUB_OUTPUT
106173
if [ "$HAS_JEST" = "true" ]; then
107-
echo "Detected: Jest"
174+
echo "Detected: Jest"
108175
fi
109176
110177
# Detect Mocha
@@ -125,7 +192,7 @@ jobs:
125192
fi
126193
echo "has_mocha=$HAS_MOCHA" >> $GITHUB_OUTPUT
127194
if [ "$HAS_MOCHA" = "true" ]; then
128-
echo "Detected: Mocha"
195+
echo "Detected: Mocha"
129196
fi
130197
131198
# ==================== PYTEST ====================
@@ -290,9 +357,69 @@ jobs:
290357
current_no_tests_found: ${{ needs.mocha-source.outputs.no_tests_found }}
291358
artifact_name: regression_mocha_${{ github.event.pull_request.number || github.run_id }}
292359

360+
# ==================== C++ (GTest/CTest) ====================
361+
# Test C++ source branch
362+
cpp-source:
363+
needs: detect-frameworks
364+
if: needs.detect-frameworks.outputs.has_cpp == 'true'
365+
uses: ./.github/workflows/test-cpp-gtest.yml
366+
with:
367+
ref: "" # Default checkout = PR branch
368+
cmake-version: ${{ inputs.cmake-version }}
369+
compiler: ${{ inputs.cpp-compiler }}
370+
build-type: ${{ inputs.cpp-build-type }}
371+
build-dir: ${{ inputs.cpp-build-dir }}
372+
cmake-args: ${{ inputs.cpp-cmake-args }}
373+
test-args: ${{ inputs.cpp-test-args }}
374+
runs_on: ${{ inputs.runs_on }}
375+
artifact_name: cpp_source_${{ github.event.pull_request.number || github.run_id }}
376+
parallel_workers: ${{ inputs.parallel_workers }}
377+
378+
# Test C++ target branch
379+
cpp-target:
380+
needs: detect-frameworks
381+
if: needs.detect-frameworks.outputs.has_cpp == 'true'
382+
uses: ./.github/workflows/test-cpp-gtest.yml
383+
with:
384+
ref: ${{ inputs.target_branch }}
385+
cmake-version: ${{ inputs.cmake-version }}
386+
compiler: ${{ inputs.cpp-compiler }}
387+
build-type: ${{ inputs.cpp-build-type }}
388+
build-dir: ${{ inputs.cpp-build-dir }}
389+
cmake-args: ${{ inputs.cpp-cmake-args }}
390+
test-args: ${{ inputs.cpp-test-args }}
391+
runs_on: ${{ inputs.runs_on }}
392+
artifact_name: cpp_target_${{ github.event.pull_request.number || github.run_id }}
393+
parallel_workers: ${{ inputs.parallel_workers }}
394+
395+
# Compare C++ results
396+
cpp-compare:
397+
needs: [detect-frameworks, cpp-source, cpp-target]
398+
if: always() && needs.detect-frameworks.outputs.has_cpp == 'true' && needs.cpp-source.result == 'success'
399+
uses: ./.github/workflows/regression-test.yml
400+
with:
401+
runs_on: ${{ inputs.runs_on }}
402+
baseline_label: ${{ inputs.target_branch }}
403+
baseline_results_artifact: cpp_target_${{ github.event.pull_request.number || github.run_id }}
404+
baseline_results_filename: test_data.json
405+
current_label: ${{ github.head_ref || github.ref_name }}
406+
current_results_artifact: cpp_source_${{ github.event.pull_request.number || github.run_id }}
407+
current_results_filename: test_data.json
408+
baseline_passed: ${{ needs.cpp-target.outputs.passed }}
409+
baseline_total: ${{ needs.cpp-target.outputs.total }}
410+
baseline_percentage: ${{ needs.cpp-target.outputs.percentage }}
411+
current_passed: ${{ needs.cpp-source.outputs.passed }}
412+
current_total: ${{ needs.cpp-source.outputs.total }}
413+
current_percentage: ${{ needs.cpp-source.outputs.percentage }}
414+
baseline_collection_errors: ${{ needs.cpp-target.outputs.collection_errors }}
415+
baseline_no_tests_found: ${{ needs.cpp-target.outputs.no_tests_found }}
416+
current_collection_errors: ${{ needs.cpp-source.outputs.collection_errors }}
417+
current_no_tests_found: ${{ needs.cpp-source.outputs.no_tests_found }}
418+
artifact_name: regression_cpp_${{ github.event.pull_request.number || github.run_id }}
419+
293420
# ==================== AGGREGATE RESULTS ====================
294421
aggregate-results:
295-
needs: [detect-frameworks, pytest-compare, jest-compare, mocha-compare]
422+
needs: [detect-frameworks, pytest-compare, jest-compare, mocha-compare, cpp-compare]
296423
if: always()
297424
runs-on: ${{ fromJSON(inputs.runs_on) }}
298425
outputs:
@@ -335,13 +462,23 @@ jobs:
335462
fi
336463
fi
337464
465+
# Check C++
466+
if [ "${{ needs.detect-frameworks.outputs.has_cpp }}" == "true" ]; then
467+
CPP_REGRESSIONS="${{ needs.cpp-compare.outputs.regression_count || '0' }}"
468+
if [ "${{ needs.cpp-compare.outputs.has_regressions }}" == "true" ]; then
469+
HAS_REGRESSIONS="true"
470+
TOTAL_REGRESSIONS=$((TOTAL_REGRESSIONS + CPP_REGRESSIONS))
471+
echo "C++ regressions: $CPP_REGRESSIONS"
472+
fi
473+
fi
474+
338475
echo "has_regressions=$HAS_REGRESSIONS" >> $GITHUB_OUTPUT
339476
echo "regression_count=$TOTAL_REGRESSIONS" >> $GITHUB_OUTPUT
340477
echo "Total regressions across all frameworks: $TOTAL_REGRESSIONS"
341478
342479
# ==================== NOTIFICATIONS ====================
343480
notify:
344-
needs: [detect-frameworks, pytest-source, pytest-target, pytest-compare, jest-source, jest-target, jest-compare, mocha-source, mocha-target, mocha-compare, aggregate-results]
481+
needs: [detect-frameworks, pytest-source, pytest-target, pytest-compare, jest-source, jest-target, jest-compare, mocha-source, mocha-target, mocha-compare, cpp-source, cpp-target, cpp-compare, aggregate-results]
345482
if: always() && needs.aggregate-results.outputs.has_regressions == 'true'
346483
runs-on: ${{ fromJSON(inputs.runs_on) }}
347484
steps:
@@ -356,7 +493,7 @@ jobs:
356493
357494
MSG="**Test Regression Alert**\n"
358495
MSG+="PR #${{ github.event.pull_request.number }}: ${{ github.event.pull_request.title }}\n"
359-
MSG+="\`${{ github.head_ref }}\` -> \`${{ inputs.target_branch }}\`\n\n"
496+
MSG+="\`${{ github.head_ref }}\` \`${{ inputs.target_branch }}\`\n\n"
360497
361498
# Pytest results
362499
if [ "${{ needs.detect-frameworks.outputs.has_pytest }}" == "true" ]; then
@@ -391,6 +528,17 @@ jobs:
391528
MSG+="\n"
392529
fi
393530
531+
# C++ results
532+
if [ "${{ needs.detect-frameworks.outputs.has_cpp }}" == "true" ]; then
533+
MSG+="**C++:**\n"
534+
MSG+=" Source: ${{ needs.cpp-source.outputs.passed }}/${{ needs.cpp-source.outputs.total }}\n"
535+
MSG+=" Target: ${{ needs.cpp-target.outputs.passed }}/${{ needs.cpp-target.outputs.total }}\n"
536+
if [ "${{ needs.cpp-compare.outputs.has_regressions }}" == "true" ]; then
537+
MSG+=" Regressions: ${{ needs.cpp-compare.outputs.regression_count }}\n"
538+
fi
539+
MSG+="\n"
540+
fi
541+
394542
MSG+="Total Regressions: ${{ needs.aggregate-results.outputs.regression_count }}\n\n"
395543
MSG+="[View Run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
396544

0 commit comments

Comments
 (0)