@@ -123,3 +123,154 @@ jobs:
123123 working-directory : ./cmake-build/tests
124124 run : |
125125 valgrind --leak-check=full --track-origins=yes --error-exitcode=1 ./ovum_tests
126+
127+ style-check :
128+ name : Code style check with clang-format
129+ runs-on : ubuntu-latest
130+ steps :
131+ - uses : actions/checkout@v4
132+
133+ - name : Install clang-format
134+ run : |
135+ sudo apt-get update && sudo apt-get -y install clang-format
136+
137+ - name : Check code style
138+ run : |
139+ # Find all C++ source files
140+ find . -name "*.cpp" -o -name "*.hpp" -o -name "*.c" -o -name "*.h" | \
141+ grep -v "./build/" | grep -v "./cmake-build" | grep -v "./_deps/" | \
142+ xargs clang-format --dry-run --Werror
143+
144+ - name : Comment on style issues
145+ if : failure()
146+ uses : actions/github-script@v7
147+ with :
148+ script : |
149+ const fs = require('fs');
150+ const { execSync } = require('child_process');
151+
152+ try {
153+ // Get list of files that need formatting
154+ const files = execSync('find . -name "*.cpp" -o -name "*.hpp" -o -name "*.c" -o -name "*.h" | grep -v "./build/" | grep -v "./cmake-build" | grep -v "./_deps/"', { encoding: 'utf8' }).trim().split('\n');
155+
156+ let comment = '## 🎨 Code Style Issues Found\n\n';
157+ comment += 'The following files have formatting issues:\n\n';
158+
159+ for (const file of files) {
160+ try {
161+ const result = execSync(`clang-format --dry-run --Werror "${file}" 2>&1`, { encoding: 'utf8' });
162+ } catch (error) {
163+ comment += `- \`${file}\`: Formatting issues detected\n`;
164+ }
165+ }
166+
167+ comment += '\nPlease run `clang-format -i <file>` to fix formatting issues.';
168+
169+ github.rest.issues.createComment({
170+ issue_number: context.issue.number,
171+ owner: context.repo.owner,
172+ repo: context.repo.repo,
173+ body: comment
174+ });
175+ } catch (error) {
176+ console.log('Could not create comment:', error.message);
177+ }
178+
179+ code-quality-check :
180+ name : Code quality check with clang-tidy
181+ runs-on : ubuntu-latest
182+ steps :
183+ - uses : actions/checkout@v4
184+
185+ - name : Install clang-tidy
186+ run : |
187+ sudo apt-get update && sudo apt-get -y install clang-tidy
188+
189+ - name : Create CMake cache
190+ run : |
191+ cmake -S . -B cmake-build-tidy -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
192+
193+ - name : Run clang-tidy
194+ run : |
195+ # Find all C++ source files
196+ find . -name "*.cpp" -o -name "*.hpp" | \
197+ grep -v "./build/" | grep -v "./cmake-build" | grep -v "./_deps/" | \
198+ xargs clang-tidy -p cmake-build-tidy --warnings-as-errors=* --format-style=file || true
199+
200+ - name : Count warnings and errors
201+ id : count_issues
202+ run : |
203+ # Run clang-tidy and capture output
204+ find . -name "*.cpp" -o -name "*.hpp" | \
205+ grep -v "./build/" | grep -v "./cmake-build" | grep -v "./_deps/" | \
206+ xargs clang-tidy -p cmake-build-tidy --format-style=file > tidy_output.txt 2>&1 || true
207+
208+ # Count errors and warnings
209+ errors=$(grep -c "error:" tidy_output.txt || echo "0")
210+ warnings=$(grep -c "warning:" tidy_output.txt || echo "0")
211+
212+ echo "errors=$errors" >> $GITHUB_OUTPUT
213+ echo "warnings=$warnings" >> $GITHUB_OUTPUT
214+
215+ # Fail if more than 3 warnings or any errors
216+ if [ "$errors" -gt 0 ] || [ "$warnings" -gt 3 ]; then
217+ echo "clang-tidy found $errors errors and $warnings warnings"
218+ exit 1
219+ fi
220+
221+ - name : Comment on quality issues
222+ if : failure()
223+ uses : actions/github-script@v7
224+ with :
225+ script : |
226+ const fs = require('fs');
227+
228+ try {
229+ let comment = '## 🔍 Code Quality Issues Found\n\n';
230+
231+ if (fs.existsSync('tidy_output.txt')) {
232+ const output = fs.readFileSync('tidy_output.txt', 'utf8');
233+ const lines = output.split('\n');
234+
235+ let currentFile = '';
236+ let hasIssues = false;
237+
238+ for (const line of lines) {
239+ if (line.includes('error:') || line.includes('warning:')) {
240+ const parts = line.split(':');
241+ if (parts.length >= 4) {
242+ const file = parts[0];
243+ const lineNum = parts[1];
244+ const message = parts.slice(3).join(':').trim();
245+
246+ if (file !== currentFile) {
247+ if (hasIssues) comment += '\n';
248+ comment += `### \`${file}\`\n\n`;
249+ currentFile = file;
250+ hasIssues = true;
251+ }
252+
253+ const issueType = line.includes('error:') ? '❌ Error' : '⚠️ Warning';
254+ comment += `- **Line ${lineNum}**: ${issueType} - ${message}\n`;
255+ }
256+ }
257+ }
258+
259+ if (!hasIssues) {
260+ comment += 'No specific issues found in the output.';
261+ }
262+ } else {
263+ comment += 'Could not read clang-tidy output.';
264+ }
265+
266+ comment += '\n\nPlease review and fix the issues above.';
267+
268+ github.rest.issues.createComment({
269+ issue_number: context.issue.number,
270+ owner: context.repo.owner,
271+ repo: context.repo.repo,
272+ body: comment
273+ });
274+ } catch (error) {
275+ console.log('Could not create comment:', error.message);
276+ }
0 commit comments