From c504557c03bada0df465218890d8843c74826939 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 15 Dec 2020 14:40:49 +0100 Subject: [PATCH 01/11] dist/tools/ci: add harness to annotate static tests in Github Actions --- .github/workflows/static-test.yml | 1 + dist/tools/ci/github_annotate.sh | 60 +++++++++++++++++++++++++++++++ dist/tools/ci/static_tests.sh | 3 ++ 3 files changed, 64 insertions(+) create mode 100644 dist/tools/ci/github_annotate.sh diff --git a/.github/workflows/static-test.yml b/.github/workflows/static-test.yml index 7d17466598fc..4529dc39dcc1 100644 --- a/.github/workflows/static-test.yml +++ b/.github/workflows/static-test.yml @@ -29,6 +29,7 @@ jobs: run: | docker run --rm \ -e CI_BASE_BRANCH=master_upstream \ + -e GITHUB_RUN_ID=${GITHUB_RUN_ID} \ -v $(pwd):/data/riotbuild \ riot/riotbuild:latest \ make static-test diff --git a/dist/tools/ci/github_annotate.sh b/dist/tools/ci/github_annotate.sh new file mode 100644 index 000000000000..0dbbb1c13c29 --- /dev/null +++ b/dist/tools/ci/github_annotate.sh @@ -0,0 +1,60 @@ +# Copyright 2020 Martine S. Lenders +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +LOG=cat +LOGFILE= +OUTFILE=github_annotate_outfile.log + +github_annotate_setup() { + if [ -n "${GITHUB_RUN_ID}" ]; then + LOGFILE=run-${GITHUB_RUN_ID}.log + LOG="tee -a ${LOGFILE}" + fi +} + +github_annotate_is_on() { + test -n "${LOGFILE}" + return $? +} + +_escape() { + # see https://stackoverflow.com/a/1252191/11921757 + echo -e "$1" | sed -e ':a' -e 'N' -e '$!ba' \ + -e 's/%/%25/g' -e 's/\r/%0D/g' -e 's/\n/%0A/g' +} + +github_annotate_error() { + if [ -n "${GITHUB_RUN_ID}" ]; then + FILENAME="${1}" + LINENUM="${2}" + DETAILS="$(_escape "${3}")" + echo "::error file=${FILENAME},line=${LINENUM}::${DETAILS}" >> ${OUTFILE} + fi +} + +github_annotate_warning() { + if [ -n "${GITHUB_RUN_ID}" ]; then + FILENAME="${1}" + LINENUM="${2}" + DETAILS="$(_escape "${3}")" + echo "::warning file=${FILENAME},line=${LINENUM}::${DETAILS}" >> ${OUTFILE} + fi +} + +github_annotate_teardown() { + if [ -n "${LOGFILE}" ]; then + rm -f ${LOGFILE} + LOGFILE= + fi +} + +github_annotate_report_last_run() { + if [ -n "${GITHUB_RUN_ID}" -a -f "${OUTFILE}" ]; then + # de-duplicate errors + sort -u ${OUTFILE} >&2 + fi + rm -f ${OUTFILE} +} diff --git a/dist/tools/ci/static_tests.sh b/dist/tools/ci/static_tests.sh index 09a6a3e9e7ea..cfaccd69e469 100755 --- a/dist/tools/ci/static_tests.sh +++ b/dist/tools/ci/static_tests.sh @@ -10,6 +10,8 @@ # directory for more details. # +. $(dirname "$0")/github_annotate.sh + function print_result { local RED="\033[0;31m" local GREEN="\033[0;32m" @@ -47,6 +49,7 @@ function run { (printf "%s\n" "$OUT" | while IFS= read -r line; do printf "\t%s\n" "$line"; done) echo "" fi + github_annotate_report_last_run } RESULT=0 From a447fbe4b57c791474ddc58e08568d21df971f6a Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 15 Dec 2020 14:41:51 +0100 Subject: [PATCH 02/11] tools/whitespacecheck: annotate errors in Github Action --- dist/tools/whitespacecheck/check.sh | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/dist/tools/whitespacecheck/check.sh b/dist/tools/whitespacecheck/check.sh index 565ca57f5741..a0eedee68cec 100755 --- a/dist/tools/whitespacecheck/check.sh +++ b/dist/tools/whitespacecheck/check.sh @@ -6,6 +6,8 @@ # General Public License v2.1. See the file LICENSE in the top level # directory for more details. +. "$(dirname "$0")/../ci/github_annotate.sh" + IGNORE=$(awk '{ printf ":!%s ", $0 }' "$(dirname "$0")/ignore_list.txt") # If no branch but an option is given, unset BRANCH. @@ -23,6 +25,10 @@ else fi fi +# sets +# - LOG to tee output into for later parsing +# - LOGFILE to parse GitHub annotations into +github_annotate_setup # select files to check if [ -z "${BRANCH}" ]; then @@ -30,17 +36,30 @@ if [ -z "${BRANCH}" ]; then fi git -c core.whitespace="tab-in-indent,tabwidth=4" \ - diff --check "$(git merge-base "${BRANCH}" HEAD)" -- *.[ch] ${IGNORE} - + diff --check "$(git merge-base "${BRANCH}" HEAD)" -- *.[ch] ${IGNORE} \ + | ${LOG} RESULT=$? # Git regards any trailing white space except `\n` as an error so `\r` is # checked here, too git -c core.whitespace="trailing-space" \ - diff --check "$(git merge-base "${BRANCH}" HEAD)" -- . ${IGNORE} + diff --check "$(git merge-base "${BRANCH}" HEAD)" -- . ${IGNORE} \ + | ${LOG} TRAILING_RESULT=$? +if github_annotate_is_on; then + grep "^.\+:[0-9]\+:" "${LOGFILE}" | while read line; do + FILENAME=$(echo "${line}" | cut -d: -f1) + LINENR=$(echo "${line}" | cut -d: -f2) + DETAILS=$(echo "${line}" | cut -d: -f3- | + sed -e 's/^[ \t]*//' -e 's/[ \t]*$//') + github_annotate_error "${FILENAME}" "${LINENR}" "${DETAILS}" + done +fi + +github_annotate_teardown + if [ ${TRAILING_RESULT} -ne 0 ] || [ ${RESULT} -ne 0 ] then echo "ERROR: This change introduces new whitespace errors" From 8bf64a685a673cfe0cbc6f9fd837c906a98fabcb Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 15 Dec 2020 20:18:38 +0100 Subject: [PATCH 03/11] dist/tools/ci: Add README.md --- dist/tools/ci/README.md | 72 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 dist/tools/ci/README.md diff --git a/dist/tools/ci/README.md b/dist/tools/ci/README.md new file mode 100644 index 000000000000..cb02e3e78f4a --- /dev/null +++ b/dist/tools/ci/README.md @@ -0,0 +1,72 @@ +CI specific scripts +=================== + +Static tests +------------ + +The [static_tests.sh] script runs all static tests and outputs them in a unified +output. You can also run this script by running `make static-test` in the base +directory. + +To add a new static test, just write a `check.sh` script or call your static +checker directly and add it to the list of static tests in [static_tests.sh]: + +```sh +ENV1=foobar ENV2=snafu run --args +``` + +Github annotations +------------------ +Using [github_annotate.sh] you can generate [Github annotations] for your +tests. You can generate both warnings and errors. Before doing anything however, +you include [github_annotate.sh]\ (assuming `${RIOTTOOLS is set to}` [dist/tools/]) + +```sh +. "${RIOTTOOLS}"/ci/github_annotate.sh +``` + +and set-up the mechanism + +```sh +github_annotate_setup +``` + +If your tests generate output you now can pipe that to the file `${LOGFILE}` by +using `${LOG}`, e.g. + +```sh +my_awesome_test | ${LOG} +``` + +Don't worry, your test will function normal still, if you don't run it in a +Github Action! + +Now you can use `github_annotate_error` and `github_annotate_warning` to +generate the actual errors and warnings. Both commands expect 3 parameters: +1. `FILENAME`: The name of the file the warning or error occurred in, +2. `LINENUM`: The number of the line the warning or error occurred in, and +3. `DETAILS`: Some descriptive details or the message of your warning or error. + +You can parse those from `${LOGFILE}` (e.g. using tools such as `grep`, `sed`, +or `awk`) or generate them on the fly, if your script allows for that. E.g. + +```sh +cat ${LOGFILE} | grep '^.*:[0-9]\+:' | while read error; do + github_annotate_error \ + $(echo "${error}" | cut -d: -f1) \ + $(echo "${error}" | cut -d: -f2) \ + $(echo "${error}" | cut -d: -f3-) +done +``` + +After all errors or warnings are annotated, call `github_annotate_teardown` to +finish annotations. + +**Note:** `github_annotate_report_last_run` is called within [static_tests.sh] +to attach the actual annotations to your PR. You don't need to call it from +within your test if you are adding that test to [static_tests.sh]. + +[static_tests.sh]: ./static_tests.sh +[Github annotations]: https://github.blog/2018-12-14-introducing-check-runs-and-annotations/ +[github_annotate.sh]: ./github_annotate.sh +[dist/tools]: ../ From 0aab760a48c8098811b757b2cc2e9b25b30acde7 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 15 Dec 2020 14:42:11 +0100 Subject: [PATCH 04/11] REMOVE ME! just for testing --- dist/tools/whitespacecheck/check.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dist/tools/whitespacecheck/check.sh b/dist/tools/whitespacecheck/check.sh index a0eedee68cec..0cced2986607 100755 --- a/dist/tools/whitespacecheck/check.sh +++ b/dist/tools/whitespacecheck/check.sh @@ -36,7 +36,7 @@ if [ -z "${BRANCH}" ]; then fi git -c core.whitespace="tab-in-indent,tabwidth=4" \ - diff --check "$(git merge-base "${BRANCH}" HEAD)" -- *.[ch] ${IGNORE} \ + diff --check "$(git merge-base "${BRANCH}" HEAD)" -- *.[ch] ${IGNORE} \ | ${LOG} RESULT=$? @@ -44,7 +44,7 @@ RESULT=$? # checked here, too git -c core.whitespace="trailing-space" \ diff --check "$(git merge-base "${BRANCH}" HEAD)" -- . ${IGNORE} \ - | ${LOG} + | ${LOG} TRAILING_RESULT=$? @@ -67,3 +67,4 @@ then else exit 0 fi + From 2063971a6c6d891893d323e0abbf3e82eef6b743 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 15 Dec 2020 22:06:14 +0100 Subject: [PATCH 05/11] fixup! dist/tools/ci: add harness to annotate static tests in Github Actions --- dist/tools/ci/github_annotate.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dist/tools/ci/github_annotate.sh b/dist/tools/ci/github_annotate.sh index 0dbbb1c13c29..9b9417856d4c 100644 --- a/dist/tools/ci/github_annotate.sh +++ b/dist/tools/ci/github_annotate.sh @@ -7,6 +7,11 @@ LOG=cat LOGFILE= OUTFILE=github_annotate_outfile.log +ECHO_ESC=echo + +if [ $(ps -p $$ -o 'cmd=') = "bash" ]; then + ECHO_ESC='echo -e' +fi github_annotate_setup() { if [ -n "${GITHUB_RUN_ID}" ]; then @@ -22,7 +27,7 @@ github_annotate_is_on() { _escape() { # see https://stackoverflow.com/a/1252191/11921757 - echo -e "$1" | sed -e ':a' -e 'N' -e '$!ba' \ + ${ECHO_ESC} "$1" | sed -e ':a' -e 'N' -e '$!ba' \ -e 's/%/%25/g' -e 's/\r/%0D/g' -e 's/\n/%0A/g' } From 86172f67fcabdf0694ca0e9a5d77e0ca228bde05 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 15 Dec 2020 22:06:14 +0100 Subject: [PATCH 06/11] fixup! dist/tools/ci: add harness to annotate static tests in Github Actions --- dist/tools/ci/github_annotate.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dist/tools/ci/github_annotate.sh b/dist/tools/ci/github_annotate.sh index 9b9417856d4c..cd834d37d746 100644 --- a/dist/tools/ci/github_annotate.sh +++ b/dist/tools/ci/github_annotate.sh @@ -9,7 +9,9 @@ LOGFILE= OUTFILE=github_annotate_outfile.log ECHO_ESC=echo -if [ $(ps -p $$ -o 'cmd=') = "bash" ]; then +if ps -p $$ | grep -q '\'; then + # workaround when included in bash to escape newlines and carriage returns + # properly in _escape ECHO_ESC='echo -e' fi From 472e7db2fa9ffca49dd1ed823a027872bc4b67ad Mon Sep 17 00:00:00 2001 From: MrKevinWeiss Date: Wed, 16 Dec 2020 13:14:15 +0100 Subject: [PATCH 07/11] test --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb21b66be5f3..ac4ef0512919 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ ZZZZZZZZZZZ Z ZZZZZ -The friendly Operating System for IoT! +The friendly Operating System for IoT! RIOT is a real-time multi-threading operating system that supports a range of devices that are typically found in the Internet of Things (IoT): From 9df614aee6ec23012603c855aa46e55a67bc4efc Mon Sep 17 00:00:00 2001 From: MrKevinWeiss Date: Wed, 16 Dec 2020 14:56:34 +0100 Subject: [PATCH 08/11] test flake8 annotation --- .../compile_and_test_for_board.py | 3 +++ dist/tools/flake8/check.sh | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/dist/tools/compile_and_test_for_board/compile_and_test_for_board.py b/dist/tools/compile_and_test_for_board/compile_and_test_for_board.py index fadcca0ac164..50139f9ff981 100755 --- a/dist/tools/compile_and_test_for_board/compile_and_test_for_board.py +++ b/dist/tools/compile_and_test_for_board/compile_and_test_for_board.py @@ -108,6 +108,9 @@ MAKE = os.environ.get('MAKE', 'make') + + + class ErrorInTest(Exception): """Custom exception for a failed test. diff --git a/dist/tools/flake8/check.sh b/dist/tools/flake8/check.sh index ac69ed50a1fc..5b5ba544265d 100755 --- a/dist/tools/flake8/check.sh +++ b/dist/tools/flake8/check.sh @@ -6,6 +6,8 @@ # General Public License v2.1. See the file LICENSE in the top level # directory for more details. # +. "$(dirname "$0")/../ci/github_annotate.sh" +github_annotate_setup FLAKE8_CMD="python3 -m flake8" @@ -45,6 +47,16 @@ ${FLAKE8_CMD} --version &> /dev/null || { ERRORS=$(${FLAKE8_CMD} --config="${RIOTTOOLS}"/flake8/flake8.cfg ${FILES}) +if github_annotate_is_on; then + grep "^.\+:[0-9]\+:" "${ERRORS}" | while read line; do + FILENAME=$(echo "${line}" | cut -d: -f1) + LINENR=$(echo "${line}" | cut -d: -f2) + DETAILS=$(echo "${line}" | cut -d: -f3- | + sed -e 's/^[ \t]*//' -e 's/[ \t]*$//') + github_annotate_error "${FILENAME}" "${LINENR}" "${DETAILS}" + done +fi + if [ -n "${ERRORS}" ] then printf "%sThere are style issues in the following Python scripts:%s\n\n" "${CERROR}" "${CRESET}" From e15988fb51eee7448cf025780bcb9eb1ffb119c9 Mon Sep 17 00:00:00 2001 From: MrKevinWeiss Date: Wed, 16 Dec 2020 15:57:37 +0100 Subject: [PATCH 09/11] fixup! test flake8 annotation --- dist/tools/flake8/check.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dist/tools/flake8/check.sh b/dist/tools/flake8/check.sh index 5b5ba544265d..05c6a8dba5fe 100755 --- a/dist/tools/flake8/check.sh +++ b/dist/tools/flake8/check.sh @@ -57,6 +57,8 @@ if github_annotate_is_on; then done fi +github_annotate_teardown + if [ -n "${ERRORS}" ] then printf "%sThere are style issues in the following Python scripts:%s\n\n" "${CERROR}" "${CRESET}" From a0c8f24c3ab04c35c24ade295ff587bb3014d685 Mon Sep 17 00:00:00 2001 From: MrKevinWeiss Date: Wed, 16 Dec 2020 16:36:29 +0100 Subject: [PATCH 10/11] fixup! fixup! test flake8 annotation --- dist/tools/flake8/check.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dist/tools/flake8/check.sh b/dist/tools/flake8/check.sh index 05c6a8dba5fe..76cdd72e5cbc 100755 --- a/dist/tools/flake8/check.sh +++ b/dist/tools/flake8/check.sh @@ -47,8 +47,10 @@ ${FLAKE8_CMD} --version &> /dev/null || { ERRORS=$(${FLAKE8_CMD} --config="${RIOTTOOLS}"/flake8/flake8.cfg ${FILES}) +${FLAKE8_CMD} --config="${RIOTTOOLS}"/flake8/flake8.cfg ${FILES} | ${LOG} + if github_annotate_is_on; then - grep "^.\+:[0-9]\+:" "${ERRORS}" | while read line; do + grep "^.\+:[0-9]\+:" "${LOGFILE}" | while read line; do FILENAME=$(echo "${line}" | cut -d: -f1) LINENR=$(echo "${line}" | cut -d: -f2) DETAILS=$(echo "${line}" | cut -d: -f3- | From 4d45f02d2ba2a54e2f7396b669c74e7fed478c07 Mon Sep 17 00:00:00 2001 From: MrKevinWeiss Date: Wed, 16 Dec 2020 16:49:20 +0100 Subject: [PATCH 11/11] fixup! fixup! fixup! test flake8 annotation --- dist/tools/flake8/check.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dist/tools/flake8/check.sh b/dist/tools/flake8/check.sh index 76cdd72e5cbc..b9a7f4555627 100755 --- a/dist/tools/flake8/check.sh +++ b/dist/tools/flake8/check.sh @@ -45,9 +45,7 @@ ${FLAKE8_CMD} --version &> /dev/null || { exit 1 } -ERRORS=$(${FLAKE8_CMD} --config="${RIOTTOOLS}"/flake8/flake8.cfg ${FILES}) - -${FLAKE8_CMD} --config="${RIOTTOOLS}"/flake8/flake8.cfg ${FILES} | ${LOG} +ERRORS=$(${FLAKE8_CMD} --config="${RIOTTOOLS}"/flake8/flake8.cfg ${FILES} | ${LOG}) if github_annotate_is_on; then grep "^.\+:[0-9]\+:" "${LOGFILE}" | while read line; do