Skip to content

Commit 093b9d1

Browse files
Merge pull request #1398 from Iximiel/feature/sarif-codecheck
Adding gh integration to the codecheck workflow
2 parents 2e6f01f + 6683071 commit 093b9d1

5 files changed

Lines changed: 330 additions & 13 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ jobs:
2222
codecheck:
2323
uses: ./.github/workflows/codecheckWF.yml
2424
secrets: inherit
25+
permissions:
26+
contents: read
27+
security-events: write
2528

2629
mac:
2730
uses: ./.github/workflows/macWF.yml

.github/workflows/codecheckWF.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ env:
1616
jobs:
1717

1818
codecheck:
19+
permissions:
20+
contents: read
21+
security-events: write
1922
runs-on: ubuntu-22.04
2023
steps:
2124
- uses: actions/checkout@v6
@@ -38,6 +41,7 @@ jobs:
3841
run: |
3942
make -j 4 -C astyle
4043
- name: Checking code
44+
id: codecheck
4145
run: |
4246
# this is required so as to have all the include files in place
4347
# notice that this is done automatically in build
@@ -46,3 +50,15 @@ jobs:
4650
# then generate the links
4751
make -C src/lib/ dirslinks
4852
make codecheck
53+
- name: Upload codecheck report to gh
54+
if: failure() && steps.codecheck.outcome == 'failure'
55+
uses: github/codeql-action/upload-sarif@v4
56+
with:
57+
sarif_file: src/codecheck.sarif
58+
category: plumedcheck
59+
- name: Upload ruff report to gh
60+
if: failure() && steps.codecheck.outcome == 'failure'
61+
uses: github/codeql-action/upload-sarif@v4
62+
with:
63+
sarif_file: src/ruff.sarif
64+
category: ruff

src/maketools/codecheck

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,21 @@ fi
7979
# "head" discards the recap and awk reformat the error message
8080
cd "${basedir}"
8181
#this uses the same check in the base Makefile
82-
if which ruff &> /dev/null; then
82+
if which ruff &>/dev/null; then
8383
ruff format --check \
8484
| grep 'Would reformat' \
8585
| awk '{ printf "[%s:0] (error) :ruff_format: python ruff formatting non satisfied\n", $3 }' \
8686
>&2
87+
#human readable
8788
ruff check --output-format concise \
8889
| head -n -2 \
8990
| awk '{ printf "[%s] (error) :ruff_check: %s", substr($1,1,length($1)-1), $2;
9091
$1=$2="";
9192
print $0 }' \
9293
>&2
94+
#machine readable
95+
#ruff is "blazingly fast" and we have a few python files:
96+
ruff check --output-format sarif -o src/ruff.sarif >&2 || true
9397
else
9498
#local error message
9599
echo " codecheck did not found ruff:"
@@ -105,6 +109,7 @@ fi
105109
# we discard configurations introduced in small_vector because they are many and
106110
# get included in many files
107111
function docheck(){
112+
# With cppcheck 2.16.1 and later you can get a report already in sarif format and put it on the CI alongside the old style of output
108113
# setting up a function to not repeat the arguments
109114
# shellcheck disable=SC2086
110115
cppcheck --std=c++17 -j 4 --platform=unix64 --language=c++ \
@@ -221,4 +226,20 @@ fi
221226
echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
222227
echo
223228

229+
#just a small check to see if python is there
230+
if [[ $do_local == false ]] && python --version &>/dev/null; then
231+
# --------------------------------------------------------------------
232+
# This converst $FATAL_FILE to the sarif format,
233+
# so that it can be integrated with the codeQL stuff in the CI
234+
# SARIF is a fancy json with some specific fields
235+
#
236+
# As now this converts only things in this form:
237+
# [{file}:{line}] ({severity}) :{id}: {message}
238+
# As now the errors in the format:
239+
# [global_check] ({severity}) :{id}: {message}
240+
# are ignored
241+
242+
python maketools/sarif.py "${FATAL_FILE}" >codecheck.sarif
243+
fi
244+
224245
exit 1

src/maketools/plumedcheck

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# vim: ft=awk
33

44
# DOC: \page Plumedcheck Validating syntax with plumedcheck
5-
# DOC:
5+
# DOC:
66
# DOC: Here is a list of coding rules that are enforced by the plumedcheck script.
77
# DOC: These rules are necessary to be sure that the codebase is consistent.
88
# DOC: Code not satisfying these rules will make the automatic test on travis-ci fail.
@@ -16,7 +16,7 @@
1616

1717
TEMP=$(mktemp -t plumed.XXXXXX)
1818

19-
cat > $TEMP << \EOF
19+
cat >$TEMP <<\EOF
2020

2121
# print usage
2222
function usage(){
@@ -246,9 +246,9 @@ BEGINFILE{
246246
s=system("diff -q " FILENAME " " tempfile ">/dev/null 2>/dev/null")
247247
# check if astyle has been applied correctly
248248
# DOC: :astyle:
249+
# DOC: The file has not been formatted correctly.
249250
# DOC: In order to keep the code readable, we use the astyle program to format
250-
# DOC: all source files. This error indicates that the reported file has not been
251-
# DOC: formatted correctly. It is important that the version of astyle and the options
251+
# DOC: all source files. It is important that the version of astyle and the options
252252
# DOC: exactly match the ones we use for testing. To this aim, you should use
253253
# DOC: a command such as `make astyle` from the plumed root directory.
254254
if(s!=0) error("astyle","astyle not satisfied")
@@ -264,6 +264,7 @@ BEGINFILE{
264264
s=system("diff -q " configurefile " " tempfile ">/dev/null 2>/dev/null")
265265
# check if autoconf has been applied correctly
266266
# DOC: :autoconf:
267+
# DOC: `./configure` is not updated.
267268
# DOC: In our git repository we distribute both `./configure` and `./configure.ac` files.
268269
# DOC: When you modify the latter, the former should be regenerated using `autoconf` and
269270
# DOC: committed to git. This error indicates that the `./configure.ac` and `./configure` files
@@ -284,6 +285,7 @@ BEGINFILE{
284285
s=system("diff -q " plumed_c " " tempfile ">/dev/null 2>/dev/null")
285286
# check if cython has been applied correctly
286287
# DOC: :python_module:
288+
# DOC: `python/plumed.c` is not updated.
287289
# DOC: In our git repository we distribute a compiled python interface
288290
# DOC: as `plumed.c` and `plumed.pyx` files.
289291
# DOC: When you modify the latter, the former should be regenerated using `cython` and
@@ -320,6 +322,7 @@ BEGINFILE{
320322
sub("^# *include +\"\\.\\./","",included_module_name);
321323
sub("/.*$","",included_module_name);
322324
# DOC: :include_dots:
325+
# DOC: Dots (`..`) in and include statement.
323326
# DOC: It is considered an error to include a file using a path starting with `../dir`,
324327
# DOC: where `dir` is not the name of a module explicitly declared as used in the Makefile.
325328
# DOC: This might result in undetected dependences between the modules, which means that
@@ -360,13 +363,15 @@ BEGINFILE{
360363
sub(">.*$","",h)
361364
# check if deprecated headers are included
362365
# DOC: :deprecated_headers:
366+
# DOC: Use of C++ deprecated headers.
363367
# DOC: There is a list of headers that have been deprecated in C++ and should not be
364368
# DOC: included. These headers should be replaced with their equivalent from the stdlib.
365369
# DOC: E.g., use `#include <cstdlib>` instead of `#include <stdlib.h>`. Notice that
366370
# DOC: using the modern header all the functions are declared inside the `std` namespace.
367371
# DOC: Also notice that we have a special exception to allow them in Plumed.h.
368372
if(h in deprecated_headers && !(module in outer_modules)) error("deprecated_header","including deprecated header " h);
369373
# DOC: :external_header: (style)
374+
# DOC: Included external headers.
370375
# DOC: Header files should possibly not include other header files from external libraries.
371376
# DOC: Indeed, once PLUMED is installed, if paths are not set correctly the include files of the other libraries
372377
# DOC: might not be reachable anymore. This is only a stylistic warning now. Notice that
@@ -383,13 +388,15 @@ BEGINFILE{
383388
# check if a .inc file, which is temporary and not installed, is included in a header file.
384389
# this might create inconsistencies in the installed plumed header files.
385390
# DOC: :non_h_header:
391+
# DOC: `.inc` file included in header.
386392
# DOC: Files with `.inc` extension are generated by PLUMED while it is compiled and are
387393
# DOC: not installed. They should not be directly included in header files, otherwise
388394
# DOC: those header files could be not usable once PLUMED is installed.
389395
if(filetype=="header" && h!~"\\.h") error("non_h_header","including non '.h' file " h " in a header file");
390396
if(h~"^[A-Za-z0-9_][A-Za-z0-9_]*/") {
391397
sub("/.*$","",h)
392398
# DOC: :include_non_used_module:
399+
# DOC: Included a non used module.
393400
# DOC: When including a file in the form `"dir/file.h"`, `dir` should be an used module.
394401
# DOC: This makes sure that we do not include system files that by chance are named as PLUMED modules.
395402
# DOC: Indeed, when including `"file"` if the file is not found in the current path it is searched in
@@ -457,8 +464,8 @@ BEGINFILE{
457464
if(match($0,"^//[+]PLUMEDOC ")){
458465
doc=$NF;
459466
# DOC: :multi_doc:
460-
# DOC: An action or cltool should be documented once and only once. Notice that because of the
461-
# DOC: way the manual is generated, a cltool cannot have the same name of an action.
467+
# DOC: An action or cltool should be documented once and only once.
468+
# DOC: Notice that because of the way the manual is generated, a cltool cannot have the same name of an action.
462469
if(doc in plumed_doc) error("multi_doc","doc " doc " already at "plumed_doc[action]);
463470
plumed_doc[doc]=FILENAME ":" FNR;
464471
n=split($(NF-1),array,"_");
@@ -516,6 +523,7 @@ BEGINFILE{
516523

517524
# check that "using namespace" statements are not used in header files
518525
# DOC: :using_namespace_in_header:
526+
# DOC: `using namespace` statement in header file.
519527
# DOC: A statement `using namespace` in header files is considered bad practice. Indeed, this would imply that
520528
# DOC: any other file including that header file would be using the same namespace.
521529
# DOC: This is true also for `std` namespace, and that's why you typically find full specifications
@@ -525,13 +533,15 @@ BEGINFILE{
525533
if(module_type[module]=="default-off") {
526534
# check that "using namespace" statements are not used in source files
527535
# DOC: :using_namespace_std_in_source:
536+
# DOC: `using namespace std` in source file.
528537
# DOC: A statement `using namespace std` in a source files is considered bad practice. Indeed, it makes it difficult to
529538
# DOC: distinguish classes and functions that are taken from the standard library (such as `std::vector`) from similar
530539
# DOC: names declared locally. This is currently a style issue, but will become an error in the future.
531540
if(filetype=="source" && match($0,"using *namespace *std") && !in_plumed_doc && !in_doxygen ) style("using_namespace_std_in_source","using namespace std statement in source file")
532541
} else {
533542
# check that "using namespace" statements are not used in source files
534543
# DOC: :using_namespace_std_in_default_source:
544+
# DOC: `using namespace std` in default source file.
535545
# DOC: A statement `using namespace std` in a source files is considered bad practice. Indeed, it makes it difficult to
536546
# DOC: distinguish classes and functions that are taken from the standard library (such as `std::vector`) from similar
537547
# DOC: names declared locally. This is currently an error for default modules.
@@ -552,6 +562,7 @@ BEGINFILE{
552562
# take note of used HAS macros
553563
if(plumed_usehas_file[string,FILENAME]!="used") information("used_has",string);
554564
# DOC: :used_has_in_header: (style)
565+
# DOC: Use of `__PLUMED_HAS_SOMETHING` macros in header.
555566
# DOC: Using `__PLUMED_HAS_SOMETHING` macros in headers should be avoided since
556567
# DOC: it could make it difficult to make sure the same macros are correctly defined
557568
# DOC: when using PLUMED as a library. This is only a stylistic warning now. Notice that
@@ -579,11 +590,13 @@ ENDFILE{
579590
# check for namespaces
580591
if(found_non_preprocessor_lines && (filetype=="source" || filetype=="header") && !(module in outer_modules) ){
581592
# DOC: :missing_namespace_plmd:
593+
# DOC: Missing namespace `PLMD`.
582594
# DOC: Every source file should contain a `PLMD` namespace.
583595
# DOC: Notice that files in the "outer modules" `wrapper` and `main`, that is those that
584596
# DOC: are not included in the kernel library, are exempted from this rule.
585597
if(!found_namespace_plmd) error("missing_namespace_plmd","missing PLMD namespace");
586598
# DOC: :missing_namespace_module:
599+
# DOC: Missing module namespace.
587600
# DOC: Every source file should contain a sub namespace with the same name of the module itself.
588601
# DOC: Notice that there are important exceptions to this rule:
589602
# DOC: - "outer modules" `wrapper` and `main`, that are not included in the kernel library.
@@ -595,6 +608,7 @@ ENDFILE{
595608
if(filetype=="header"){
596609
# this can be done only if module name is known:
597610
# DOC: :missing_guard:
611+
# DOC: Missing header guard.
598612
# DOC: Every header file should contain a proper guard to avoid double inclusion.
599613
# DOC: The format of the guard is fixed and should be `__PLUMED_modulename_filename_h`, where
600614
# DOC: `modulename` is the name of the module and `filename` is the name of the file, without suffix.
@@ -615,6 +629,7 @@ ENDFILE{
615629
}
616630
if(notfound){
617631
# DOC: :non_existing_cpp:
632+
# DOC: Header file lacks compantion source file.
618633
# DOC: For every header file there should exist a corresponding source file with the same name.
619634
# DOC: Notice that dummy headers that only include another header or which only define preprocessor
620635
# DOC: macros are exempted from this rule.
@@ -626,6 +641,7 @@ ENDFILE{
626641
noIncludes=0;
627642
sub("^# *include","");
628643
# DOC: :non_included_h:
644+
# DOC: Source files must include the corrisponding header file.
629645
# DOC: The source file corresponding to a header file (that is: with the same name) should include it as the first included file.
630646
# DOC: This is to make sure that all the header files that we install can be individually included and compiled.
631647
if($1!="\"" file "\"") error("non_included_h","file " file " is a header but " cppfile " does not include it as first include");
@@ -649,8 +665,7 @@ END{
649665
for(action in registered_actions){
650666
if(!(action in plumed_doc_action)){
651667
# DOC: :undocumented_action:
652-
# DOC: Every action that is registered with `PLUMED_REGISTER_ACTION` should also be documented
653-
# DOC: in a PLUMEDOC page.
668+
# DOC: Every action that is registered with `PLUMED_REGISTER_ACTION` should also be documented in a PLUMEDOC page.
654669
style("undocumented_action","action " action " at " registered_actions[action] " is not documented")
655670
} else if(!(action in provide_examples)){
656671
# DOC: :action_without_examples:
@@ -700,17 +715,17 @@ END{
700715
for(has in plumed_usehas){
701716
if(!(has in plumed_definehas)){
702717
# DOC: :undefined_has:
703-
# DOC: Every macro in the form `__PLUMED_HAS_SOMETHING` that is used in the code
704-
# DOC: should be defined in configure.ac. This check is made to avoid errors with mis-typed macros.
718+
# DOC: Every macro in the form `__PLUMED_HAS_SOMETHING` that is used in the code should be defined in configure.ac.
719+
# DOC: This check is made to avoid errors with mis-typed macros.
705720
error("undefined_has","has " has " at " plumed_usehas[has] " is not defined")
706721
}
707722
}
708723

709724
for(has in plumed_definehas){
710725
if(!(has in plumed_usehas)){
711726
# DOC: :unused_has:
712-
# DOC: Every macro in the form `__PLUMED_HAS_SOMETHING` that is defined in configure.ac
713-
# DOC: should be used at least once in the code. This check is made to avoid errors with mis-typed macros.
727+
# DOC: Every macro in the form `__PLUMED_HAS_SOMETHING` that is defined in configure.ac should be used at least once in the code.
728+
# DOC: This check is made to avoid errors with mis-typed macros.
714729
error("unused_has","has " has " at " plumed_definehas[has] " is not used")
715730
}
716731
}

0 commit comments

Comments
 (0)