@@ -10,10 +10,16 @@ jobs:
1010 steps :
1111 - uses : actions/checkout@v4
1212
13+ - name : Install MinGW toolchain
14+ shell : powershell
15+ run : |
16+ choco install mingw --yes --no-progress
17+ echo "C:\tools\mingw64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
18+
1319 - name : Create CMake cache
1420 run : |
15- cmake -S . -B cmake-build-release -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles"
16- cmake -S . -B cmake-build-debug -DCMAKE_BUILD_TYPE=Debug -G "Unix Makefiles"
21+ cmake -S . -B cmake-build-release -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles"
22+ cmake -S . -B cmake-build-debug -DCMAKE_BUILD_TYPE=Debug -G "MinGW Makefiles"
1723
1824 - name : Build main target
1925 shell : bash
@@ -27,14 +33,16 @@ jobs:
2733
2834 - name : Run program
2935 working-directory : .\cmake-build-release
36+ shell : bash
3037 run : |
31- .\ ovum.exe --help
38+ ./ ovum.exe --help
3239
3340 - name : Run tests
3441 working-directory : .\cmake-build-debug
42+ shell : bash
3543 run : |
36- echo "Currently unable to run tests on Windows Latest MinGW. See https://gitmemories.com/cristianadam/HelloWorld/issues/12 and https://github.com/microsoft/vscode-cmake-tools/issues/2451"
37- % .\ovum_tests.exe
44+ # ./ovum_tests.exe
45+ echo "Tests are not run on Windows MinGW due to issues with the test runner"
3846
3947 build-matrix :
4048 name : Tests and application run on ${{ matrix.config.name }}
@@ -123,3 +131,198 @@ jobs:
123131 working-directory : ./cmake-build/tests
124132 run : |
125133 valgrind --leak-check=full --track-origins=yes --error-exitcode=1 ./ovum_tests
134+
135+ style-check :
136+ name : Code style check with clang-format
137+ runs-on : ubuntu-latest
138+ steps :
139+ - uses : actions/checkout@v4
140+
141+ - name : Install clang-format
142+ run : |
143+ sudo apt-get update && sudo apt-get -y install clang-format
144+
145+ - name : Check code style
146+ shell : bash
147+ run : |
148+ mapfile -t files < <(git ls-files '*.c' '*.cpp' '*.h' '*.hpp')
149+
150+ if [ "${#files[@]}" -eq 0 ]; then
151+ echo "No C/C++ files to check."
152+ exit 0
153+ fi
154+
155+ clang-format --dry-run --Werror "${files[@]}" 2>format_output.txt || {
156+ cat format_output.txt
157+ exit 1
158+ }
159+
160+ - name : Comment on style issues
161+ if : failure() && github.event_name == 'pull_request'
162+ uses : actions/github-script@v7
163+ with :
164+ script : |
165+ const fs = require('fs');
166+ const { execSync } = require('child_process');
167+
168+ try {
169+ // Get list of files that need formatting
170+ const rawFiles = execSync('git ls-files "*.c" "*.cpp" "*.h" "*.hpp"', { encoding: 'utf8' }).trim();
171+
172+ if (!rawFiles) {
173+ console.log('No files require formatting checks.');
174+ return;
175+ }
176+
177+ const files = rawFiles.split('\n');
178+
179+ let comment = '## 🎨 Code Style Issues Found\n\n';
180+ comment += 'The following files have formatting issues:\n\n';
181+ let hasIssues = false;
182+
183+ for (const file of files) {
184+ try {
185+ const result = execSync(`clang-format --dry-run --Werror "${file}" 2>&1`, { encoding: 'utf8' });
186+ } catch (error) {
187+ comment += `- \`${file}\`: Formatting issues detected\n`;
188+ hasIssues = true;
189+ }
190+ }
191+
192+ if (!hasIssues) {
193+ comment += 'No files with formatting issues were detected.';
194+ } else {
195+ comment += '\nPlease run `clang-format -i <file>` to fix formatting issues.';
196+ }
197+
198+ github.rest.issues.createComment({
199+ issue_number: context.issue.number,
200+ owner: context.repo.owner,
201+ repo: context.repo.repo,
202+ body: comment
203+ });
204+ } catch (error) {
205+ console.log('Could not create comment:', error.message);
206+ }
207+
208+ code-quality-check :
209+ name : Code quality check with clang-tidy
210+ runs-on : ubuntu-latest
211+ steps :
212+ - uses : actions/checkout@v4
213+
214+ - name : Install clang-tidy
215+ run : |
216+ sudo apt-get update && sudo apt-get -y install clang-tidy
217+
218+ - name : Create CMake cache
219+ run : |
220+ cmake -S . -B cmake-build-tidy -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
221+
222+ - name : Run clang-tidy
223+ shell : bash
224+ run : |
225+ mapfile -t files < <(git ls-files '*.c' '*.cpp')
226+
227+ if [ "${#files[@]}" -eq 0 ]; then
228+ echo "No C/C++ files to analyze."
229+ echo "" > tidy_output.txt
230+ exit 0
231+ fi
232+
233+ echo "Running clang-tidy on ${#files[@]} files..."
234+ clang-tidy "${files[@]}" -p cmake-build-tidy --format-style=file > tidy_output.txt 2>&1 || true
235+
236+ # Ensure file exists and is readable
237+ if [ ! -f tidy_output.txt ]; then
238+ echo "" > tidy_output.txt
239+ fi
240+
241+ - name : Count warnings and errors
242+ id : count_issues
243+ run : |
244+ # Count errors and warnings - handle empty file case
245+ if [ ! -s tidy_output.txt ]; then
246+ errors=0
247+ warnings=0
248+ else
249+ errors=$(grep -c "error:" tidy_output.txt 2>/dev/null || echo "0")
250+ warnings=$(grep -c "warning:" tidy_output.txt 2>/dev/null || echo "0")
251+ fi
252+
253+ # Ensure we have clean integer values
254+ errors=$(echo "$errors" | tr -d '\n' | head -c 10)
255+ warnings=$(echo "$warnings" | tr -d '\n' | head -c 10)
256+
257+ # Default to 0 if empty or non-numeric
258+ errors=${errors:-0}
259+ warnings=${warnings:-0}
260+
261+ echo "errors=$errors" >> $GITHUB_OUTPUT
262+ echo "warnings=$warnings" >> $GITHUB_OUTPUT
263+
264+ echo "Found $errors errors and $warnings warnings"
265+
266+ # Fail if more than 3 warnings or any errors
267+ if [ "$errors" -gt 0 ] || [ "$warnings" -gt 3 ]; then
268+ echo "clang-tidy found $errors errors and $warnings warnings"
269+ cat tidy_output.txt
270+ exit 1
271+ fi
272+
273+ - name : Comment on quality issues
274+ if : failure() && github.event_name == 'pull_request'
275+ uses : actions/github-script@v7
276+ with :
277+ script : |
278+ const fs = require('fs');
279+
280+ try {
281+ let comment = '## 🔍 Code Quality Issues Found\n\n';
282+
283+ if (fs.existsSync('tidy_output.txt')) {
284+ const output = fs.readFileSync('tidy_output.txt', 'utf8');
285+ const lines = output.split('\n');
286+
287+ let currentFile = '';
288+ let hasIssues = false;
289+
290+ for (const line of lines) {
291+ if (line.includes('error:') || line.includes('warning:')) {
292+ const parts = line.split(':');
293+ if (parts.length >= 4) {
294+ const file = parts[0];
295+ const lineNum = parts[1];
296+ const message = parts.slice(3).join(':').trim();
297+
298+ if (file !== currentFile) {
299+ if (hasIssues) comment += '\n';
300+ comment += `### \`${file}\`\n\n`;
301+ currentFile = file;
302+ hasIssues = true;
303+ }
304+
305+ const issueType = line.includes('error:') ? '❌ Error' : '⚠️ Warning';
306+ comment += `- **Line ${lineNum}**: ${issueType} - ${message}\n`;
307+ }
308+ }
309+ }
310+
311+ if (!hasIssues) {
312+ comment += 'No specific issues found in the output.';
313+ }
314+ } else {
315+ comment += 'Could not read clang-tidy output.';
316+ }
317+
318+ comment += '\n\nPlease review and fix the issues above.';
319+
320+ github.rest.issues.createComment({
321+ issue_number: context.issue.number,
322+ owner: context.repo.owner,
323+ repo: context.repo.repo,
324+ body: comment
325+ });
326+ } catch (error) {
327+ console.log('Could not create comment:', error.message);
328+ }
0 commit comments