All of lore.kernel.org
 help / color / mirror / Atom feed
* [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck)
@ 2021-12-26 18:49 Ricardo Martincoski
  2021-12-26 18:49 ` [Buildroot] [PATCH 1/5] utils/check-package: prepare to run external tools Ricardo Martincoski
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Ricardo Martincoski @ 2021-12-26 18:49 UTC (permalink / raw)
  To: buildroot; +Cc: Joachim Wiberg, Ricardo Martincoski

Hello,

This small series (called series2 below) is built on top of [1] (called series1)
specially for its patches 1 (check-package unit tests) and 4 (script
utils/docker-run that eases to run locally commands in the docker image in order
to have stable results across machines).

So:
series1 1/4 utils/checkpackagelib: add unit tests
series1 2/4 support/docker: add python3-pytest
series1 3/4 utils/checkpackagelib: run unit tests on GitLab CI
series1 4/4 utils/docker-run: new script
series2 1/5 utils/check-package: prepare to run external tools
series2 2/5 utils/checkpackagelib: warn about executable files
series2 3/5 utils/checkpackagelib/lib_sysv: check SysV init scripts
series2 4/5 support/docker: add shellcheck
series2 5/5 utils/checkpackagelib/lib_sysv: run shellcheck

This series is also related to [2].
Cc: Joachim Wiberg <troglobit@gmail.com>
See an example output for patch [2]:
|$ utils/docker-run utils/check-package -vvv package/inadyn/S70inadyn
|package/inadyn/S70inadyn:24: should be indented with tabs, see package/busybox/S01syslogd
|< tab  >< tab  >< tab  >  -- $INADYN_ARGS
|package/inadyn/S70inadyn:0: This file does not need to be executable, just make sure you use '$(INSTALL) -D -m 0755' in the .mk file
|74 lines processed
|2 warnings generated

This series is also related to [3].
Perhaps if both series are accepted, we can add cross-reference between the doc
and the tool:
- check-package can point to a manual entry
- the doc can mention to use check-package directly for SysV init script
- the doc can mention to use check-package inside docker image using
  utils/docker-run

What this series IS NOT:
 - a complete rework of all SysV init scripts in the tree;
 - an automated way to rework SysV init scripts;
 - the ultimate checker for SysV init scripts that catches all possible errors;
 - something to enable in GitLab CI in the short term.

What this series IS (hopefully):
 - a helper for developers willing to rework one SysV init script at a time;
 - something that can be extended to check more common mistakes when reworking a
   SysV init script with package/busybox/S01syslogd as base;
 - a few years from now we can eventually enable the check in GitLab CI when all
   SysV init script got reworked.

In [4] one can see an example of all warnings that would be generated for all
scripts in the tree.
NOTICE that no warnings are generated for package/busybox/S01syslogd, as
expected.
At the end see some extracts from [4] with some interesting results (thanks to
shellcheck).

NOTICE that as a consequence of using shellcheck, there will be cases that will
need shellcheck disables, just like S01syslogd already does:
|	# shellcheck disable=SC2086 # we need the word splitting

[1] http://patchwork.ozlabs.org/project/buildroot/list/?series=275236
[2] http://patchwork.ozlabs.org/project/buildroot/patch/20211205102907.2836980-3-troglobit@gmail.com/
[3] http://patchwork.ozlabs.org/project/buildroot/patch/20211205102010.2834942-1-troglobit@gmail.com/
[4] https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/1921130201

Regards,
Ricardo

Extracts from [4] with some interesting results:
|board/intel/galileo/rootfs_overlay/etc/init.d/S09modload: ignored
|
|package/pigpio/S50pigpio:4: For PIDFILE use the same pattern found in package/busybox/S01syslogd
|PIDFILE="/var/run/pigpio.pid"
|PIDFILE="/var/run/$DAEMON.pid"
|
|package/pigpio/S50pigpio:0: filename should be S<number><number><deamon name>, see package/busybox/S01syslogd
|expecting S<number><number>pigpiod
|
|package/motion/S99motion:5: Do not include path in DAEMON, see package/busybox/S01syslogd
|DAEMON=/usr/bin/$NAME
|DAEMON="$NAME"
|
|package/motion/S99motion:23: should be indented with tabs, see package/busybox/S01syslogd
|  start)
|
|package/motion/S99motion:0: run 'shellcheck' and fix the warnings
|In package/motion/S99motion line 13:
|< tab  >printf "Stopping $NAME: "
|               ^----------------^ SC2059: Don't use variables in the printf format string. Use printf "..%s.." "$foo".
|
|package/mender/S42mender:0: run 'shellcheck' and fix the warnings
|In package/mender/S42mender line 13:
|< tab  >     -a "$(readlink /var/lib/mender)" = "/var/run/mender" ]
|             ^-- SC2166: Prefer [ p ] && [ q ] as [ p -a q ] is not well defined.
|In package/mender/S42mender line 29:
|< tab  >[ $? = 0 ] && echo "OK" || echo "FAIL"
|          ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
|
|package/eudev/S10udev:45: consecutive empty lines
|
|package/mrp/S65mrp:0: filename should be S<number><number><deamon name>, see package/busybox/S01syslogd
|expecting S<number><number>mrp_server
|
|package/bluez5_utils/S40bluetooth:0: filename should be S<number><number><deamon name>, see package/busybox/S01syslogd
|expecting S<number><number>bluetoothd
|
|package/bluez5_utils/S40bluetooth:0: This file does not need to be executable, just make sure you use '$(INSTALL) -D -m 0755' in the .mk file
|
|package/netatalk/S50netatalk:33: empty line at end of file
|
|package/iptables/S35iptables:0: run 'shellcheck' and fix the warnings
|In package/iptables/S35iptables line 5:
|IPTABLES_ARGS=""
|^-----------^ SC2034: IPTABLES_ARGS appears unused. Verify use (or export if used externally).
|
|package/rpcbind/S30rpcbind:38: empty line at end of file
|
|In package/dhcp/S80dhcp-relay line 31:
|DHCRELAYPID=/var/run/dhcrelay.pid
|^---------^ SC2034: DHCRELAYPID appears unused. Verify use (or export if used externally).
|
|package/busybox/S10mdev:9: consecutive empty lines
|
|package/busybox/S10mdev:0: run 'shellcheck' and fix the warnings
|In package/busybox/S10mdev line 11:
|< tab  >echo -n "Starting $DAEMON... "
|             ^-- SC2039: In POSIX sh, echo flags are undefined.
|
|In package/targetcli-fb/S50target line 7:
|< tab  >local ret
|        ^-------^ SC2039: In POSIX sh, 'local' is undefined.
|
|package/oracle-mysql/S97mysqld:0: run 'shellcheck' and fix the warnings
|In package/oracle-mysql/S97mysqld line 28:
|< tab  >< tab  >< tab  >kill `cat /run/mysql/mysqld.pid`
|                             ^-------------------------^ SC2046: Quote this to prevent word splitting.
|                             ^-------------------------^ SC2006: Use $(...) notation instead of legacy backticked `...`.
|Did you mean:
|< tab  >< tab  >< tab  >kill $(cat /run/mysql/mysqld.pid)
|
|package/dbus/S30dbus:0: run 'shellcheck' and fix the warnings
|In package/dbus/S30dbus line 58:
|        if [ -f /var/lock/subsys/$servicename ]; then
|                                 ^----------^ SC2154: servicename is referenced but not assigned.
|                                 ^----------^ SC2086: Double quote to prevent globbing and word splitting.
|Did you mean:
|        if [ -f /var/lock/subsys/"$servicename" ]; then
|
|package/smcroute/S41smcroute:0: This file does not need to be executable, just make sure you use '$(INSTALL) -D -m 0755' in the .mk file
|package/c-icap/S96cicap:0: run 'shellcheck' and fix the warnings
|In package/c-icap/S96cicap line 12:
|< tab  >[ $? == 0 ] && echo "OK" || echo "FAIL"
|          ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
|             ^-- SC2039: In POSIX sh, == in place of = is undefined.
|
|package/polkit/S50polkit:0: This file does not need to be executable, just make sure you use '$(INSTALL) -D -m 0755' in the .mk file
|
|package/polkit/S50polkit:0: run 'shellcheck' and fix the warnings
|In package/polkit/S50polkit line 43:
|< tab  >start|stop|restart|reload)
|                           ^----^ SC2221: This pattern always overrides a later one on line 45.
|In package/polkit/S50polkit line 45:
|< tab  >reload)
|        ^----^ SC2222: This pattern never matches because of a previous pattern on line 43.
|
|package/restorecond/S02restorecond:0: run 'shellcheck' and fix the warnings
|In package/restorecond/S02restorecond line 52:
|< tab  >< tab  >echo $"Usage: $0 {start|stop|restart|reload}"
|                     ^-- SC2039: In POSIX sh, $".." is undefined.
|
|package/earlyoom/S02earlyoom:0: run 'shellcheck' and fix the warnings
|In package/earlyoom/S02earlyoom line 10:
|start() {
|        ^-- SC1009: The mentioned syntax error was in this brace group.
|In package/earlyoom/S02earlyoom line 11:
|< tab  >printf() 'Starting %s: ' "$DAEMON"
|        ^-- SC1073: Couldn't parse this function. Fix to allow more checks.
|                 ^-- SC1064: Expected a { to open the function definition.
|                 ^-- SC1072:  Fix any mentioned problems and try again.
|
|package/watchdogd/S01watchdogd:0: This file does not need to be executable, just make sure you use '$(INSTALL) -D -m 0755' in the .mk file
|
|package/brltty/S10brltty:0: run 'shellcheck' and fix the warnings
|In package/brltty/S10brltty line 17:
|restart() {
|^-- SC2120: restart references arguments, but none are ever passed.
|
|package/audit/S02auditd:0: run 'shellcheck' and fix the warnings
|In package/audit/S02auditd line 13:
|CONFIG=/etc/audit/auditd.conf
|^----^ SC2034: CONFIG appears unused. Verify use (or export if used externally).
|
|package/network-manager/S45network-manager:40: consecutive empty lines
|package/network-manager/S45network-manager:41: consecutive empty lines
|package/network-manager/S45network-manager:41: empty line at end of file
|
|package/tftpd/S80tftpd-hpa:0: run 'shellcheck' and fix the warnings
|In package/tftpd/S80tftpd-hpa line 11:
|PIDFILE=/var/run/$NAME.pid
|^-----^ SC2034: PIDFILE appears unused. Verify use (or export if used externally).
|
|package/owfs/S60owfs:0: run 'shellcheck' and fix the warnings
|In package/owfs/S60owfs line 1:
|NAME="owfs"
|^-- SC2148: Tips depend on target shell and yours is unknown. Add a shebang.
|
|package/owfs/S55owserver:0: run 'shellcheck' and fix the warnings
|In package/owfs/S55owserver line 1:
|NAME="owserver"
|^-- SC2148: Tips depend on target shell and yours is unknown. Add a shebang.
|
|package/transmission/S92transmission:0: run 'shellcheck' and fix the warnings
|In package/transmission/S92transmission line 50:
|DAEMON=$(which $NAME)
|         ^---^ SC2230: which is non-standard. Use builtin 'command -v' instead.

Ricardo Martincoski (5):
  utils/check-package: prepare to run external tools
  utils/checkpackagelib: warn about executable files
  utils/checkpackagelib/lib_sysv: check SysV init scripts
  support/docker: add shellcheck
  utils/checkpackagelib/lib_sysv: run shellcheck

 support/docker/Dockerfile              |   1 +
 utils/check-package                    |  39 ++++++--
 utils/checkpackagelib/base.py          |  11 +++
 utils/checkpackagelib/lib_config.py    |   1 +
 utils/checkpackagelib/lib_hash.py      |   1 +
 utils/checkpackagelib/lib_mk.py        |   1 +
 utils/checkpackagelib/lib_patch.py     |   1 +
 utils/checkpackagelib/lib_sysv.py      |  67 +++++++++++++
 utils/checkpackagelib/test_lib_sysv.py | 131 +++++++++++++++++++++++++
 utils/checkpackagelib/test_tool.py     | 112 +++++++++++++++++++++
 utils/checkpackagelib/tool.py          |  23 +++++
 11 files changed, 382 insertions(+), 6 deletions(-)
 create mode 100644 utils/checkpackagelib/lib_sysv.py
 create mode 100644 utils/checkpackagelib/test_lib_sysv.py
 create mode 100644 utils/checkpackagelib/test_tool.py
 create mode 100644 utils/checkpackagelib/tool.py

-- 
2.25.1

_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Buildroot] [PATCH 1/5] utils/check-package: prepare to run external tools
  2021-12-26 18:49 [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck) Ricardo Martincoski
@ 2021-12-26 18:49 ` Ricardo Martincoski
  2021-12-26 18:49 ` [Buildroot] [PATCH 2/5] utils/checkpackagelib: warn about executable files Ricardo Martincoski
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Ricardo Martincoski @ 2021-12-26 18:49 UTC (permalink / raw)
  To: buildroot; +Cc: Ricardo Martincoski

Some file formats have well-established syntax checkers.
One example of this is the tool 'shellcheck' that can analyse shell
scripts for common mistakes.

There is no reason to reimplement such tools in check-package, when we
can just call them.

Add the ability to check-package to call external tools that will run
once for each file to be analysed.
For simplicity, when the tool generated one or more warnings, count it
as a single warning from check-package, that can display something like
this:

|$ ./utils/check-package  package/unscd/S46unscd
|package/unscd/S46unscd:0: run 'shellcheck' and fix the warnings
|25 lines processed
|1 warnings generated

|$ ./utils/check-package -vvvvvvvvvvvvvvvv package/unscd/S46unscd
|package/unscd/S46unscd:0: run 'shellcheck' and fix the warnings
|In package/unscd/S46unscd line 9:
|        printf "Starting ${NAME}: "
|               ^------------------^ SC2059: Don't use variables in the printf format string. Use printf "..%s.." "$foo".
|In package/unscd/S46unscd line 11:
|        [ $? -eq 0 ] && echo "OK" || echo "FAIL"
|          ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
|In package/unscd/S46unscd line 14:
|        printf "Stopping ${NAME}: "
|               ^------------------^ SC2059: Don't use variables in the printf format string. Use printf "..%s.." "$foo".
|In package/unscd/S46unscd line 16:
|        [ $? -eq 0 ] && echo "OK" || echo "FAIL"
|          ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
|For more information:
|  https://www.shellcheck.net/wiki/SC2059 -- Don't use variables in the printf...
|  https://www.shellcheck.net/wiki/SC2181 -- Check exit code directly with e.g...
|25 lines processed
|1 warnings generated

In this first commit, add only the ability for check-package to call
external tools and not an example of such tool, as adding each tool to
call may need update to the docker image and can lead to it's own
discussion on how to implement.

Signed-off-by: Ricardo Martincoski <ricardo.martincoski@gmail.com>
---
Please read the cover letter before applying.
---
 utils/check-package           | 34 ++++++++++++++++++++++++++++------
 utils/checkpackagelib/base.py |  8 ++++++++
 2 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/utils/check-package b/utils/check-package
index a959fef079..5fb430902d 100755
--- a/utils/check-package
+++ b/utils/check-package
@@ -8,6 +8,7 @@ import re
 import six
 import sys
 
+import checkpackagelib.base
 import checkpackagelib.lib_config
 import checkpackagelib.lib_hash
 import checkpackagelib.lib_mk
@@ -87,9 +88,7 @@ def get_lib_from_filename(fname):
     return None
 
 
-def is_a_check_function(m):
-    if not inspect.isclass(m):
-        return False
+def common_inspect_rules(m):
     # do not call the base class
     if m.__name__.startswith("_"):
         return False
@@ -100,6 +99,22 @@ def is_a_check_function(m):
     return True
 
 
+def is_a_check_function(m):
+    if not inspect.isclass(m):
+        return False
+    if not issubclass(m, checkpackagelib.base._CheckFunction):
+        return False
+    return common_inspect_rules(m)
+
+
+def is_external_tool(m):
+    if not inspect.isclass(m):
+        return False
+    if not issubclass(m, checkpackagelib.base._Tool):
+        return False
+    return common_inspect_rules(m)
+
+
 def print_warnings(warnings):
     # Avoid the need to use 'return []' at the end of every check function.
     if warnings is None:
@@ -121,14 +136,16 @@ def check_file_using_lib(fname):
         if flags.verbose >= VERBOSE_LEVEL_TO_SHOW_IGNORED_FILES:
             print("{}: ignored".format(fname))
         return nwarnings, nlines
-    classes = inspect.getmembers(lib, is_a_check_function)
+    internal_functions = inspect.getmembers(lib, is_a_check_function)
+    external_tools = inspect.getmembers(lib, is_external_tool)
+    all_checks = internal_functions + external_tools
 
     if flags.dry_run:
-        functions_to_run = [c[0] for c in classes]
+        functions_to_run = [c[0] for c in all_checks]
         print("{}: would run: {}".format(fname, functions_to_run))
         return nwarnings, nlines
 
-    objects = [c[1](fname, flags.manual_url) for c in classes]
+    objects = [c[1](fname, flags.manual_url) for c in internal_functions]
 
     for cf in objects:
         nwarnings += print_warnings(cf.before())
@@ -148,6 +165,11 @@ def check_file_using_lib(fname):
     for cf in objects:
         nwarnings += print_warnings(cf.after())
 
+    tools = [c[1](fname) for c in external_tools]
+
+    for tool in tools:
+        nwarnings += print_warnings(tool.run())
+
     return nwarnings, nlines
 
 
diff --git a/utils/checkpackagelib/base.py b/utils/checkpackagelib/base.py
index 9544a64e5a..73da925a03 100644
--- a/utils/checkpackagelib/base.py
+++ b/utils/checkpackagelib/base.py
@@ -16,3 +16,11 @@ class _CheckFunction(object):
 
     def after(self):
         pass
+
+
+class _Tool(object):
+    def __init__(self, filename):
+        self.filename = filename
+
+    def run(self):
+        pass
-- 
2.25.1

_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Buildroot] [PATCH 2/5] utils/checkpackagelib: warn about executable files
  2021-12-26 18:49 [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck) Ricardo Martincoski
  2021-12-26 18:49 ` [Buildroot] [PATCH 1/5] utils/check-package: prepare to run external tools Ricardo Martincoski
@ 2021-12-26 18:49 ` Ricardo Martincoski
  2021-12-26 18:49 ` [Buildroot] [PATCH 3/5] utils/checkpackagelib/lib_sysv: check SysV init scripts Ricardo Martincoski
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Ricardo Martincoski @ 2021-12-26 18:49 UTC (permalink / raw)
  To: buildroot; +Cc: Ricardo Martincoski

Currently there are no .mk, Config.in, .patch or .hash files with
executable permissions in the tree.
But we don't want to have that.

So warn when a file checked by check-package has executable permission.

This check will be reused when testing SysV init scripts in the tree.

Signed-off-by: Ricardo Martincoski <ricardo.martincoski@gmail.com>
---
Please read the cover letter before applying.
---
 utils/checkpackagelib/lib_config.py |  1 +
 utils/checkpackagelib/lib_hash.py   |  1 +
 utils/checkpackagelib/lib_mk.py     |  1 +
 utils/checkpackagelib/lib_patch.py  |  1 +
 utils/checkpackagelib/test_tool.py  | 41 +++++++++++++++++++++++++++++
 utils/checkpackagelib/tool.py       |  8 ++++++
 6 files changed, 53 insertions(+)
 create mode 100644 utils/checkpackagelib/test_tool.py
 create mode 100644 utils/checkpackagelib/tool.py

diff --git a/utils/checkpackagelib/lib_config.py b/utils/checkpackagelib/lib_config.py
index c348eec399..b05831f2c3 100644
--- a/utils/checkpackagelib/lib_config.py
+++ b/utils/checkpackagelib/lib_config.py
@@ -10,6 +10,7 @@ from checkpackagelib.lib import ConsecutiveEmptyLines  # noqa: F401
 from checkpackagelib.lib import EmptyLastLine          # noqa: F401
 from checkpackagelib.lib import NewlineAtEof           # noqa: F401
 from checkpackagelib.lib import TrailingSpace          # noqa: F401
+from checkpackagelib.tool import NotExecutable         # noqa: F401
 
 
 def _empty_or_comment(text):
diff --git a/utils/checkpackagelib/lib_hash.py b/utils/checkpackagelib/lib_hash.py
index 3e381119a5..c67046e16d 100644
--- a/utils/checkpackagelib/lib_hash.py
+++ b/utils/checkpackagelib/lib_hash.py
@@ -10,6 +10,7 @@ from checkpackagelib.lib import ConsecutiveEmptyLines  # noqa: F401
 from checkpackagelib.lib import EmptyLastLine          # noqa: F401
 from checkpackagelib.lib import NewlineAtEof           # noqa: F401
 from checkpackagelib.lib import TrailingSpace          # noqa: F401
+from checkpackagelib.tool import NotExecutable         # noqa: F401
 
 
 def _empty_line_or_comment(text):
diff --git a/utils/checkpackagelib/lib_mk.py b/utils/checkpackagelib/lib_mk.py
index 88e4b15c7c..153754b6f1 100644
--- a/utils/checkpackagelib/lib_mk.py
+++ b/utils/checkpackagelib/lib_mk.py
@@ -13,6 +13,7 @@ from checkpackagelib.lib import EmptyLastLine          # noqa: F401
 from checkpackagelib.lib import NewlineAtEof           # noqa: F401
 from checkpackagelib.lib import TrailingSpace          # noqa: F401
 from checkpackagelib.lib import Utf8Characters         # noqa: F401
+from checkpackagelib.tool import NotExecutable         # noqa: F401
 
 # used in more than one check
 start_conditional = ["ifdef", "ifeq", "ifndef", "ifneq"]
diff --git a/utils/checkpackagelib/lib_patch.py b/utils/checkpackagelib/lib_patch.py
index e4e914b7f0..caee36158f 100644
--- a/utils/checkpackagelib/lib_patch.py
+++ b/utils/checkpackagelib/lib_patch.py
@@ -8,6 +8,7 @@ import re
 
 from checkpackagelib.base import _CheckFunction
 from checkpackagelib.lib import NewlineAtEof           # noqa: F401
+from checkpackagelib.tool import NotExecutable         # noqa: F401
 
 
 class ApplyOrder(_CheckFunction):
diff --git a/utils/checkpackagelib/test_tool.py b/utils/checkpackagelib/test_tool.py
new file mode 100644
index 0000000000..e9e0838103
--- /dev/null
+++ b/utils/checkpackagelib/test_tool.py
@@ -0,0 +1,41 @@
+import os
+import pytest
+import re
+import tempfile
+import checkpackagelib.tool as m
+
+workdir = os.path.join(tempfile.mkdtemp(suffix='-checkpackagelib-test-tool'))
+workdir_regex = re.compile(r'/tmp/tmp[^/]*-checkpackagelib-test-tool')
+
+
+def check_file(tool, filename, string, permissions=None):
+    script = os.path.join(workdir, filename)
+    with open(script, 'wb') as f:
+        f.write(string.encode())
+    if permissions:
+        os.chmod(script, permissions)
+    obj = tool(script)
+    result = obj.run()
+    if result is None:
+        return []
+    return [workdir_regex.sub('dir', r) for r in result]
+
+
+NotExecutable = [
+    ('664',
+     'package.mk',
+     0o664,
+     '',
+     []),
+    ('775',
+     'package.mk',
+     0o775,
+     '',
+     ["dir/package.mk:0: This file does not need to be executable"]),
+    ]
+
+
+@pytest.mark.parametrize('testname,filename,permissions,string,expected', NotExecutable)
+def test_NotExecutable(testname, filename, permissions, string, expected):
+    warnings = check_file(m.NotExecutable, filename, string, permissions)
+    assert warnings == expected
diff --git a/utils/checkpackagelib/tool.py b/utils/checkpackagelib/tool.py
new file mode 100644
index 0000000000..f2007be1ff
--- /dev/null
+++ b/utils/checkpackagelib/tool.py
@@ -0,0 +1,8 @@
+import os
+from checkpackagelib.base import _Tool
+
+
+class NotExecutable(_Tool):
+    def run(self):
+        if os.access(self.filename, os.X_OK):
+            return ["{}:0: This file does not need to be executable".format(self.filename)]
-- 
2.25.1

_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Buildroot] [PATCH 3/5] utils/checkpackagelib/lib_sysv: check SysV init scripts
  2021-12-26 18:49 [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck) Ricardo Martincoski
  2021-12-26 18:49 ` [Buildroot] [PATCH 1/5] utils/check-package: prepare to run external tools Ricardo Martincoski
  2021-12-26 18:49 ` [Buildroot] [PATCH 2/5] utils/checkpackagelib: warn about executable files Ricardo Martincoski
@ 2021-12-26 18:49 ` Ricardo Martincoski
  2021-12-26 18:49 ` [Buildroot] [PATCH 4/5] support/docker: add shellcheck Ricardo Martincoski
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Ricardo Martincoski @ 2021-12-26 18:49 UTC (permalink / raw)
  To: buildroot; +Cc: Ricardo Martincoski

Enable the common checks:
 - consecutive empty lines
 - empty last line
 - missing new line at end of file
 - trailing space
 - warn for executable files, with the hint to instead use
   '$(INSTALL) -D -m 0755' in the .mk file

Check indent with tabs:
 - add a simple check function to warn only when the indent is done
   using spaces or a mix of tabs and spaces. It does not check indenting
   levels, but it already makes the review easier, since it
   diferentiates spaces and tabs.

Check variables:
 - check DAEMON is defined
 - when DAEMON is defined, check the filename is in the form S01daemon
 - when PIDFILE is defined, expect it to be in /var/run and defined
   using $DAEMON.

Signed-off-by: Ricardo Martincoski <ricardo.martincoski@gmail.com>
---
Please read the cover letter before applying.
---
 utils/check-package                    |   5 +
 utils/checkpackagelib/base.py          |   3 +
 utils/checkpackagelib/lib_sysv.py      |  66 +++++++++++++
 utils/checkpackagelib/test_lib_sysv.py | 131 +++++++++++++++++++++++++
 utils/checkpackagelib/test_tool.py     |  25 +++++
 utils/checkpackagelib/tool.py          |   2 +-
 6 files changed, 231 insertions(+), 1 deletion(-)
 create mode 100644 utils/checkpackagelib/lib_sysv.py
 create mode 100644 utils/checkpackagelib/test_lib_sysv.py

diff --git a/utils/check-package b/utils/check-package
index 5fb430902d..f64daed84c 100755
--- a/utils/check-package
+++ b/utils/check-package
@@ -13,6 +13,7 @@ import checkpackagelib.lib_config
 import checkpackagelib.lib_hash
 import checkpackagelib.lib_mk
 import checkpackagelib.lib_patch
+import checkpackagelib.lib_sysv
 
 VERBOSE_LEVEL_TO_SHOW_IGNORED_FILES = 3
 flags = None  # Command line arguments.
@@ -66,6 +67,8 @@ DO_NOT_CHECK_INTREE = re.compile(r"|".join([
     r"toolchain/toolchain-external/pkg-toolchain-external\.mk$",
     ]))
 
+SYSV_INIT_SCRIPT_FILENAME = re.compile(r"/S\d\d[^/]+$")
+
 
 def get_lib_from_filename(fname):
     if flags.intree_only:
@@ -85,6 +88,8 @@ def get_lib_from_filename(fname):
         return checkpackagelib.lib_mk
     if fname.endswith(".patch"):
         return checkpackagelib.lib_patch
+    if SYSV_INIT_SCRIPT_FILENAME.search(fname):
+        return checkpackagelib.lib_sysv
     return None
 
 
diff --git a/utils/checkpackagelib/base.py b/utils/checkpackagelib/base.py
index 73da925a03..f666e4110b 100644
--- a/utils/checkpackagelib/base.py
+++ b/utils/checkpackagelib/base.py
@@ -24,3 +24,6 @@ class _Tool(object):
 
     def run(self):
         pass
+
+    def hint(self):
+        return ""
diff --git a/utils/checkpackagelib/lib_sysv.py b/utils/checkpackagelib/lib_sysv.py
new file mode 100644
index 0000000000..77e6283b25
--- /dev/null
+++ b/utils/checkpackagelib/lib_sysv.py
@@ -0,0 +1,66 @@
+import os
+import re
+
+from checkpackagelib.base import _CheckFunction
+from checkpackagelib.lib import ConsecutiveEmptyLines  # noqa: F401
+from checkpackagelib.lib import EmptyLastLine          # noqa: F401
+from checkpackagelib.lib import NewlineAtEof           # noqa: F401
+from checkpackagelib.lib import TrailingSpace          # noqa: F401
+from checkpackagelib.tool import NotExecutable as NotExecutable_base
+
+
+class Indent(_CheckFunction):
+    INDENTED_WITH_SPACES = re.compile(r"^[\t]* ")
+
+    def check_line(self, lineno, text):
+        if self.INDENTED_WITH_SPACES.search(text.rstrip()):
+            return ["{}:{}: should be indented with tabs, see package/busybox/S01syslogd".format(self.filename, lineno),
+                    text]
+
+
+class NotExecutable(NotExecutable_base):
+    def hint(self):
+        return ", just make sure you use '$(INSTALL) -D -m 0755' in the .mk file"
+
+
+# avoid check-package running both the parent and child classes. NOTE: NotExecutable_base.__name__ returns 'NotExecutable'
+del NotExecutable_base
+
+
+class Variables(_CheckFunction):
+    DAEMON_VAR = re.compile(r"^DAEMON=[\"']{0,1}([^\"']*)[\"']{0,1}")
+    PIDFILE_PATTERN = re.compile(r"/var/run/(\$DAEMON|\$\{DAEMON\}).pid")
+    PIDFILE_VAR = re.compile(r"^PIDFILE=[\"']{0,1}([^\"']*)[\"']{0,1}")
+
+    def before(self):
+        self.name = None
+
+    def check_line(self, lineno, text):
+        name_found = self.DAEMON_VAR.search(text.rstrip())
+        if name_found:
+            if self.name:
+                return ["{}:{}: DAEMON variable redefined, see package/busybox/S01syslogd".format(self.filename, lineno),
+                        text]
+            self.name = name_found.group(1)
+            if '/' in self.name:
+                self.name = os.path.basename(self.name)  # to be used in after() to check the expected filename
+                return ["{}:{}: Do not include path in DAEMON, see package/busybox/S01syslogd".format(self.filename, lineno),
+                        text,
+                        'DAEMON="{}"'.format(self.name)]
+            return
+
+        pidfile_found = self.PIDFILE_VAR.search(text.rstrip())
+        if pidfile_found:
+            pidfile = pidfile_found.group(1)
+            if not self.PIDFILE_PATTERN.match(pidfile):
+                return ["{}:{}: For PIDFILE use the same pattern found in package/busybox/S01syslogd".format(self.filename, lineno),
+                        text,
+                        'PIDFILE="/var/run/$DAEMON.pid"']
+
+    def after(self):
+        if self.name is None:
+            return ["{}:0: DAEMON variable not defined, see package/busybox/S01syslogd".format(self.filename)]
+        expected_filename = re.compile(r"S\d\d{}$".format(self.name))
+        if not expected_filename.match(os.path.basename(self.filename)):
+            return ["{}:0: filename should be S<number><number><deamon name>, see package/busybox/S01syslogd".format(self.filename),
+                    "expecting S<number><number>{}".format(self.name)]
diff --git a/utils/checkpackagelib/test_lib_sysv.py b/utils/checkpackagelib/test_lib_sysv.py
new file mode 100644
index 0000000000..290539c0e4
--- /dev/null
+++ b/utils/checkpackagelib/test_lib_sysv.py
@@ -0,0 +1,131 @@
+import os
+import pytest
+import re
+import tempfile
+import checkpackagelib.test_util as util
+import checkpackagelib.lib_sysv as m
+from checkpackagelib.test_tool import check_file as tool_check_file
+
+workdir = os.path.join(tempfile.mkdtemp(suffix='-checkpackagelib-test-sysv'))
+workdir_regex = re.compile(r'/tmp/tmp[^/]*-checkpackagelib-test-sysv')
+
+
+Indent = [
+    ('empty file',
+     'any',
+     '',
+     []),
+    ('empty line',
+     'any',
+     '\n',
+     []),
+    ('ignore whitespace',
+     'any',
+     ' \n',
+     []),
+    ('spaces',
+     'any',
+     'case "$1" in\n'
+     '  start)',
+     [['any:2: should be indented with tabs, see package/busybox/S01syslogd',
+       '  start)']]),
+    ('tab',
+     'any',
+     'case "$1" in\n'
+     '\tstart)',
+     []),
+    ('tabs and spaces',
+     'any',
+     'case "$1" in\n'
+     '\t  start)',
+     [['any:2: should be indented with tabs, see package/busybox/S01syslogd',
+       '\t  start)']]),
+    ('spaces and tabs',
+     'any',
+     'case "$1" in\n'
+     '  \tstart)',
+     [['any:2: should be indented with tabs, see package/busybox/S01syslogd',
+       '  \tstart)']]),
+    ]
+
+
+@pytest.mark.parametrize('testname,filename,string,expected', Indent)
+def test_Indent(testname, filename, string, expected):
+    warnings = util.check_file(m.Indent, filename, string)
+    assert warnings == expected
+
+
+NotExecutable = [
+    ('SysV',
+     'sh-shebang.sh',
+     0o775,
+     '#!/bin/sh',
+     ["dir/sh-shebang.sh:0: This file does not need to be executable,"
+      " just make sure you use '$(INSTALL) -D -m 0755' in the .mk file"]),
+    ]
+
+
+@pytest.mark.parametrize('testname,filename,permissions,string,expected', NotExecutable)
+def test_NotExecutable(testname, filename, permissions, string, expected):
+    warnings = tool_check_file(m.NotExecutable, filename, string, permissions)
+    assert warnings == expected
+
+
+Variables = [
+    ('empty file',
+     'any',
+     '',
+     [['any:0: DAEMON variable not defined, see package/busybox/S01syslogd']]),
+    ('daemon and pidfile ok',
+     'package/busybox/S01syslogd',
+     'DAEMON="syslogd"\n'
+     'PIDFILE="/var/run/$DAEMON.pid"\n',
+     []),
+    ('wrong filename',
+     'package/busybox/S01syslog',
+     'DAEMON="syslogd"\n'
+     'PIDFILE="/var/run/${DAEMON}.pid"\n',
+     [['package/busybox/S01syslog:0: filename should be S<number><number><deamon name>, see package/busybox/S01syslogd',
+       'expecting S<number><number>syslogd']]),
+    ('no pidfile ok',
+     'S99something',
+     'DAEMON="something"\n',
+     []),
+    ('hardcoded pidfile',
+     'S99something',
+     'DAEMON="something"\n'
+     'PIDFILE="/var/run/something.pid"\n',
+     [['S99something:2: For PIDFILE use the same pattern found in package/busybox/S01syslogd',
+       'PIDFILE="/var/run/something.pid"\n',
+       'PIDFILE="/var/run/$DAEMON.pid"']]),
+    ('redefined daemon',
+     'S50any',
+     'DAEMON="any"\n'
+     'DAEMON="other"\n',
+     [['S50any:2: DAEMON variable redefined, see package/busybox/S01syslogd',
+       'DAEMON="other"\n']]),
+    ('daemon name with dash',
+     'S82cups-browsed',
+     'DAEMON="cups-browsed"',
+     []),
+    ('daemon with path',
+     'S50avahi-daemon',
+     'DAEMON=/usr/sbin/avahi-daemon',
+     [['S50avahi-daemon:1: Do not include path in DAEMON, see package/busybox/S01syslogd',
+       'DAEMON=/usr/sbin/avahi-daemon',
+       'DAEMON="avahi-daemon"']]),
+    ('daemon with path and wrong filename',
+     'S50avahi',
+     'DAEMON=/usr/sbin/avahi-daemon',
+     [['S50avahi:1: Do not include path in DAEMON, see package/busybox/S01syslogd',
+       'DAEMON=/usr/sbin/avahi-daemon',
+       'DAEMON="avahi-daemon"'],
+      ['S50avahi:0: filename should be S<number><number><deamon name>, see package/busybox/S01syslogd',
+       'expecting S<number><number>avahi-daemon']]),
+    ]
+
+
+@pytest.mark.parametrize('testname,filename,string,expected', Variables)
+def test_Variables(testname, filename, string, expected):
+    warnings = util.check_file(m.Variables, filename, string)
+    assert warnings == expected
diff --git a/utils/checkpackagelib/test_tool.py b/utils/checkpackagelib/test_tool.py
index e9e0838103..aab7cb51c9 100644
--- a/utils/checkpackagelib/test_tool.py
+++ b/utils/checkpackagelib/test_tool.py
@@ -39,3 +39,28 @@ NotExecutable = [
 def test_NotExecutable(testname, filename, permissions, string, expected):
     warnings = check_file(m.NotExecutable, filename, string, permissions)
     assert warnings == expected
+
+
+NotExecutable_hint = [
+    ('no hint',
+     "",
+     'sh-shebang.sh',
+     0o775,
+     '#!/bin/sh',
+     ["dir/sh-shebang.sh:0: This file does not need to be executable"]),
+    ('hint',
+     ", very special hint",
+     'sh-shebang.sh',
+     0o775,
+     '#!/bin/sh',
+     ["dir/sh-shebang.sh:0: This file does not need to be executable, very special hint"]),
+    ]
+
+
+@pytest.mark.parametrize('testname,hint,filename,permissions,string,expected', NotExecutable_hint)
+def test_NotExecutable_hint(testname, hint, filename, permissions, string, expected):
+    class NotExecutable(m.NotExecutable):
+        def hint(self):
+            return hint
+    warnings = check_file(NotExecutable, filename, string, permissions)
+    assert warnings == expected
diff --git a/utils/checkpackagelib/tool.py b/utils/checkpackagelib/tool.py
index f2007be1ff..e931272554 100644
--- a/utils/checkpackagelib/tool.py
+++ b/utils/checkpackagelib/tool.py
@@ -5,4 +5,4 @@ from checkpackagelib.base import _Tool
 class NotExecutable(_Tool):
     def run(self):
         if os.access(self.filename, os.X_OK):
-            return ["{}:0: This file does not need to be executable".format(self.filename)]
+            return ["{}:0: This file does not need to be executable{}".format(self.filename, self.hint())]
-- 
2.25.1

_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Buildroot] [PATCH 4/5] support/docker: add shellcheck
  2021-12-26 18:49 [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck) Ricardo Martincoski
                   ` (2 preceding siblings ...)
  2021-12-26 18:49 ` [Buildroot] [PATCH 3/5] utils/checkpackagelib/lib_sysv: check SysV init scripts Ricardo Martincoski
@ 2021-12-26 18:49 ` Ricardo Martincoski
  2022-01-09 10:52   ` Romain Naour
  2021-12-26 18:49 ` [Buildroot] [PATCH 5/5] utils/checkpackagelib/lib_sysv: run shellcheck Ricardo Martincoski
  2022-02-06 17:29 ` [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck) Arnout Vandecappelle
  5 siblings, 1 reply; 8+ messages in thread
From: Ricardo Martincoski @ 2021-12-26 18:49 UTC (permalink / raw)
  To: buildroot; +Cc: Ricardo Martincoski

Allow developers to run check-package for init scripts, that call
shellcheck, without having to install the tool.

Since the docker have a fixed version of the tool, there will be no
difference between runs in different machines.

One can call:
$ utils/docker-run utils/check-package package/package/S*
$ utils/docker-run shellcheck package/package/S*

This change also allows to eventually run check-package for init scripts
in the GitLab CI.

Signed-off-by: Ricardo Martincoski <ricardo.martincoski@gmail.com>
---
Please read the cover letter before applying.
---
 support/docker/Dockerfile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/support/docker/Dockerfile b/support/docker/Dockerfile
index 792e70e292..2b14f0f7a7 100644
--- a/support/docker/Dockerfile
+++ b/support/docker/Dockerfile
@@ -44,6 +44,7 @@ RUN apt-get install -y --no-install-recommends \
         qemu-system-arm \
         qemu-system-x86 \
         rsync \
+        shellcheck \
         subversion \
         unzip \
         wget \
-- 
2.25.1

_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Buildroot] [PATCH 5/5] utils/checkpackagelib/lib_sysv: run shellcheck
  2021-12-26 18:49 [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck) Ricardo Martincoski
                   ` (3 preceding siblings ...)
  2021-12-26 18:49 ` [Buildroot] [PATCH 4/5] support/docker: add shellcheck Ricardo Martincoski
@ 2021-12-26 18:49 ` Ricardo Martincoski
  2022-02-06 17:29 ` [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck) Arnout Vandecappelle
  5 siblings, 0 replies; 8+ messages in thread
From: Ricardo Martincoski @ 2021-12-26 18:49 UTC (permalink / raw)
  To: buildroot; +Cc: Ricardo Martincoski

For simplicity, when shellcheck returns one or more warnings, count it
as a single check-package warning.
The developer can get the full output either by running shellcheck
directly or by calling check-package with enough -v.

Examples:

|$ ./utils/docker-run utils/check-package --include Shellcheck package/polkit/S50polkit
|package/polkit/S50polkit:0: run 'shellcheck' and fix the warnings
|51 lines processed
|1 warnings generated

|$ ./utils/docker-run utils/check-package --include Shellcheck -vvvvvvvvvvv package/polkit/S50polkit
|package/polkit/S50polkit:0: run 'shellcheck' and fix the warnings
|In package/polkit/S50polkit line 43:
|< tab  >start|stop|restart|reload)
|                           ^----^ SC2221: This pattern always overrides a later one on line 45.
|In package/polkit/S50polkit line 45:
|< tab  >reload)
|        ^----^ SC2222: This pattern never matches because of a previous pattern on line 43.
|For more information:
|  https://www.shellcheck.net/wiki/SC2221 -- This pattern always overrides a l...
|  https://www.shellcheck.net/wiki/SC2222 -- This pattern never matches becaus...
|51 lines processed
|1 warnings generated

NOTICE: shellcheck results depends on the version of the tool.
This is why the examples above run inside the docker image.

Signed-off-by: Ricardo Martincoski <ricardo.martincoski@gmail.com>
---
Please read the cover letter before applying.
---
 utils/checkpackagelib/lib_sysv.py  |  1 +
 utils/checkpackagelib/test_tool.py | 46 ++++++++++++++++++++++++++++++
 utils/checkpackagelib/tool.py      | 15 ++++++++++
 3 files changed, 62 insertions(+)

diff --git a/utils/checkpackagelib/lib_sysv.py b/utils/checkpackagelib/lib_sysv.py
index 77e6283b25..786510badf 100644
--- a/utils/checkpackagelib/lib_sysv.py
+++ b/utils/checkpackagelib/lib_sysv.py
@@ -7,6 +7,7 @@ from checkpackagelib.lib import EmptyLastLine          # noqa: F401
 from checkpackagelib.lib import NewlineAtEof           # noqa: F401
 from checkpackagelib.lib import TrailingSpace          # noqa: F401
 from checkpackagelib.tool import NotExecutable as NotExecutable_base
+from checkpackagelib.tool import Shellcheck            # noqa: F401
 
 
 class Indent(_CheckFunction):
diff --git a/utils/checkpackagelib/test_tool.py b/utils/checkpackagelib/test_tool.py
index aab7cb51c9..c5c1d48dfe 100644
--- a/utils/checkpackagelib/test_tool.py
+++ b/utils/checkpackagelib/test_tool.py
@@ -64,3 +64,49 @@ def test_NotExecutable_hint(testname, hint, filename, permissions, string, expec
             return hint
     warnings = check_file(NotExecutable, filename, string, permissions)
     assert warnings == expected
+
+
+Shellcheck = [
+    ('missing shebang',
+     'empty.sh',
+     '',
+     ["dir/empty.sh:0: run 'shellcheck' and fix the warnings",
+      "In dir/empty.sh line 1:",
+      "^-- SC2148: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.",
+      "For more information:",
+      "  https://www.shellcheck.net/wiki/SC2148 -- Tips depend on target shell and y..."]),
+    ('sh shebang',
+     'sh-shebang.sh',
+     '#!/bin/sh',
+     []),
+    ('bash shebang',
+     'bash-shebang.sh',
+     '#!/bin/bash',
+     []),
+    ('2 warnings',
+     'unused.sh',
+     'unused=""',
+     ["dir/unused.sh:0: run 'shellcheck' and fix the warnings",
+      "In dir/unused.sh line 1:",
+      'unused=""',
+      "^-- SC2148: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.",
+      "^----^ SC2034: unused appears unused. Verify use (or export if used externally).",
+      "For more information:",
+      "  https://www.shellcheck.net/wiki/SC2148 -- Tips depend on target shell and y...",
+      "  https://www.shellcheck.net/wiki/SC2034 -- unused appears unused. Verify use..."]),
+    ('tab',
+     'tab.sh',
+     '\t#!/bin/sh',
+     ["dir/tab.sh:0: run 'shellcheck' and fix the warnings",
+      "In dir/tab.sh line 1:",
+      '\t#!/bin/sh',
+      "^-- SC1114: Remove leading spaces before the shebang.",
+      "For more information:",
+      "  https://www.shellcheck.net/wiki/SC1114 -- Remove leading spaces before the ..."]),
+    ]
+
+
+@pytest.mark.parametrize('testname,filename,string,expected', Shellcheck)
+def test_Shellcheck(testname, filename, string, expected):
+    warnings = check_file(m.Shellcheck, filename, string)
+    assert warnings == expected
diff --git a/utils/checkpackagelib/tool.py b/utils/checkpackagelib/tool.py
index e931272554..47f9634486 100644
--- a/utils/checkpackagelib/tool.py
+++ b/utils/checkpackagelib/tool.py
@@ -1,4 +1,5 @@
 import os
+import subprocess
 from checkpackagelib.base import _Tool
 
 
@@ -6,3 +7,17 @@ class NotExecutable(_Tool):
     def run(self):
         if os.access(self.filename, os.X_OK):
             return ["{}:0: This file does not need to be executable{}".format(self.filename, self.hint())]
+
+
+class Shellcheck(_Tool):
+    def run(self):
+        cmd = ['shellcheck', self.filename]
+        try:
+            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            stdout = p.communicate()[0]
+            processed_output = [str(line.decode().rstrip()) for line in stdout.splitlines() if line]
+            if p.returncode == 0:
+                return
+            return ["{}:0: run 'shellcheck' and fix the warnings".format(self.filename)] + processed_output
+        except FileNotFoundError:
+            return ["{}:0: failed to call 'shellcheck'".format(self.filename)]
-- 
2.25.1

_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [Buildroot] [PATCH 4/5] support/docker: add shellcheck
  2021-12-26 18:49 ` [Buildroot] [PATCH 4/5] support/docker: add shellcheck Ricardo Martincoski
@ 2022-01-09 10:52   ` Romain Naour
  0 siblings, 0 replies; 8+ messages in thread
From: Romain Naour @ 2022-01-09 10:52 UTC (permalink / raw)
  To: Ricardo Martincoski, buildroot

Hello Ricardo,

Acked-by: Romain Naour <romain.naour@smile.fr>

Best regards,
Romain


Le 26/12/2021 à 19:49, Ricardo Martincoski a écrit :
> Allow developers to run check-package for init scripts, that call
> shellcheck, without having to install the tool.
> 
> Since the docker have a fixed version of the tool, there will be no
> difference between runs in different machines.
> 
> One can call:
> $ utils/docker-run utils/check-package package/package/S*
> $ utils/docker-run shellcheck package/package/S*
> 
> This change also allows to eventually run check-package for init scripts
> in the GitLab CI.
> 
> Signed-off-by: Ricardo Martincoski <ricardo.martincoski@gmail.com>
> ---
> Please read the cover letter before applying.
> ---
>  support/docker/Dockerfile | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/support/docker/Dockerfile b/support/docker/Dockerfile
> index 792e70e292..2b14f0f7a7 100644
> --- a/support/docker/Dockerfile
> +++ b/support/docker/Dockerfile
> @@ -44,6 +44,7 @@ RUN apt-get install -y --no-install-recommends \
>          qemu-system-arm \
>          qemu-system-x86 \
>          rsync \
> +        shellcheck \
>          subversion \
>          unzip \
>          wget \
> 

_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck)
  2021-12-26 18:49 [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck) Ricardo Martincoski
                   ` (4 preceding siblings ...)
  2021-12-26 18:49 ` [Buildroot] [PATCH 5/5] utils/checkpackagelib/lib_sysv: run shellcheck Ricardo Martincoski
@ 2022-02-06 17:29 ` Arnout Vandecappelle
  5 siblings, 0 replies; 8+ messages in thread
From: Arnout Vandecappelle @ 2022-02-06 17:29 UTC (permalink / raw)
  To: Ricardo Martincoski, buildroot; +Cc: Joachim Wiberg



On 26/12/2021 19:49, Ricardo Martincoski wrote:
> Hello,
> 
> This small series (called series2 below) is built on top of [1] (called series1)
> specially for its patches 1 (check-package unit tests) and 4 (script
> utils/docker-run that eases to run locally commands in the docker image in order
> to have stable results across machines).
> 
> So:
> series1 1/4 utils/checkpackagelib: add unit tests
> series1 2/4 support/docker: add python3-pytest
> series1 3/4 utils/checkpackagelib: run unit tests on GitLab CI
> series1 4/4 utils/docker-run: new script
> series2 1/5 utils/check-package: prepare to run external tools
> series2 2/5 utils/checkpackagelib: warn about executable files
> series2 3/5 utils/checkpackagelib/lib_sysv: check SysV init scripts
> series2 4/5 support/docker: add shellcheck
> series2 5/5 utils/checkpackagelib/lib_sysv: run shellcheck

  Series applied to master.

> 
> This series is also related to [2].
> Cc: Joachim Wiberg <troglobit@gmail.com>
> See an example output for patch [2]:
> |$ utils/docker-run utils/check-package -vvv package/inadyn/S70inadyn
> |package/inadyn/S70inadyn:24: should be indented with tabs, see package/busybox/S01syslogd
> |< tab  >< tab  >< tab  >  -- $INADYN_ARGS
> |package/inadyn/S70inadyn:0: This file does not need to be executable, just make sure you use '$(INSTALL) -D -m 0755' in the .mk file
> |74 lines processed
> |2 warnings generated
> 
> This series is also related to [3].
> Perhaps if both series are accepted, we can add cross-reference between the doc
> and the tool:
> - check-package can point to a manual entry

  This I have done.

> - the doc can mention to use check-package directly for SysV init script
> - the doc can mention to use check-package inside docker image using
>    utils/docker-run

  These two I have not done.

  I've also made a few more changes, and I've put a new docker image to gitlab 
so it can be used by run-docker.

  With this tools thing in check-package, it would be nice if we could move 
flake8 in there as well. I have a post-commit hook that automatically runs 
check-package, but not flake8, and because of that it often happens that flake8 
errors slip by (on this series as well...).

  Same for shellcheck, it would be nice to run it on all scripts (particularly 
in utils/ and support/), not just the init start script.

  Regards,
  Arnout

> 
> What this series IS NOT:
>   - a complete rework of all SysV init scripts in the tree;
>   - an automated way to rework SysV init scripts;
>   - the ultimate checker for SysV init scripts that catches all possible errors;
>   - something to enable in GitLab CI in the short term.
> 
> What this series IS (hopefully):
>   - a helper for developers willing to rework one SysV init script at a time;
>   - something that can be extended to check more common mistakes when reworking a
>     SysV init script with package/busybox/S01syslogd as base;
>   - a few years from now we can eventually enable the check in GitLab CI when all
>     SysV init script got reworked.
> 
> In [4] one can see an example of all warnings that would be generated for all
> scripts in the tree.
> NOTICE that no warnings are generated for package/busybox/S01syslogd, as
> expected.
> At the end see some extracts from [4] with some interesting results (thanks to
> shellcheck).
> 
> NOTICE that as a consequence of using shellcheck, there will be cases that will
> need shellcheck disables, just like S01syslogd already does:
> |	# shellcheck disable=SC2086 # we need the word splitting
> 
> [1] http://patchwork.ozlabs.org/project/buildroot/list/?series=275236
> [2] http://patchwork.ozlabs.org/project/buildroot/patch/20211205102907.2836980-3-troglobit@gmail.com/
> [3] http://patchwork.ozlabs.org/project/buildroot/patch/20211205102010.2834942-1-troglobit@gmail.com/
> [4] https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/1921130201
> 
> Regards,
> Ricardo
> 
> Extracts from [4] with some interesting results:
> |board/intel/galileo/rootfs_overlay/etc/init.d/S09modload: ignored
> |
> |package/pigpio/S50pigpio:4: For PIDFILE use the same pattern found in package/busybox/S01syslogd
> |PIDFILE="/var/run/pigpio.pid"
> |PIDFILE="/var/run/$DAEMON.pid"
> |
> |package/pigpio/S50pigpio:0: filename should be S<number><number><deamon name>, see package/busybox/S01syslogd
> |expecting S<number><number>pigpiod
> |
> |package/motion/S99motion:5: Do not include path in DAEMON, see package/busybox/S01syslogd
> |DAEMON=/usr/bin/$NAME
> |DAEMON="$NAME"
> |
> |package/motion/S99motion:23: should be indented with tabs, see package/busybox/S01syslogd
> |  start)
> |
> |package/motion/S99motion:0: run 'shellcheck' and fix the warnings
> |In package/motion/S99motion line 13:
> |< tab  >printf "Stopping $NAME: "
> |               ^----------------^ SC2059: Don't use variables in the printf format string. Use printf "..%s.." "$foo".
> |
> |package/mender/S42mender:0: run 'shellcheck' and fix the warnings
> |In package/mender/S42mender line 13:
> |< tab  >     -a "$(readlink /var/lib/mender)" = "/var/run/mender" ]
> |             ^-- SC2166: Prefer [ p ] && [ q ] as [ p -a q ] is not well defined.
> |In package/mender/S42mender line 29:
> |< tab  >[ $? = 0 ] && echo "OK" || echo "FAIL"
> |          ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
> |
> |package/eudev/S10udev:45: consecutive empty lines
> |
> |package/mrp/S65mrp:0: filename should be S<number><number><deamon name>, see package/busybox/S01syslogd
> |expecting S<number><number>mrp_server
> |
> |package/bluez5_utils/S40bluetooth:0: filename should be S<number><number><deamon name>, see package/busybox/S01syslogd
> |expecting S<number><number>bluetoothd
> |
> |package/bluez5_utils/S40bluetooth:0: This file does not need to be executable, just make sure you use '$(INSTALL) -D -m 0755' in the .mk file
> |
> |package/netatalk/S50netatalk:33: empty line at end of file
> |
> |package/iptables/S35iptables:0: run 'shellcheck' and fix the warnings
> |In package/iptables/S35iptables line 5:
> |IPTABLES_ARGS=""
> |^-----------^ SC2034: IPTABLES_ARGS appears unused. Verify use (or export if used externally).
> |
> |package/rpcbind/S30rpcbind:38: empty line at end of file
> |
> |In package/dhcp/S80dhcp-relay line 31:
> |DHCRELAYPID=/var/run/dhcrelay.pid
> |^---------^ SC2034: DHCRELAYPID appears unused. Verify use (or export if used externally).
> |
> |package/busybox/S10mdev:9: consecutive empty lines
> |
> |package/busybox/S10mdev:0: run 'shellcheck' and fix the warnings
> |In package/busybox/S10mdev line 11:
> |< tab  >echo -n "Starting $DAEMON... "
> |             ^-- SC2039: In POSIX sh, echo flags are undefined.
> |
> |In package/targetcli-fb/S50target line 7:
> |< tab  >local ret
> |        ^-------^ SC2039: In POSIX sh, 'local' is undefined.
> |
> |package/oracle-mysql/S97mysqld:0: run 'shellcheck' and fix the warnings
> |In package/oracle-mysql/S97mysqld line 28:
> |< tab  >< tab  >< tab  >kill `cat /run/mysql/mysqld.pid`
> |                             ^-------------------------^ SC2046: Quote this to prevent word splitting.
> |                             ^-------------------------^ SC2006: Use $(...) notation instead of legacy backticked `...`.
> |Did you mean:
> |< tab  >< tab  >< tab  >kill $(cat /run/mysql/mysqld.pid)
> |
> |package/dbus/S30dbus:0: run 'shellcheck' and fix the warnings
> |In package/dbus/S30dbus line 58:
> |        if [ -f /var/lock/subsys/$servicename ]; then
> |                                 ^----------^ SC2154: servicename is referenced but not assigned.
> |                                 ^----------^ SC2086: Double quote to prevent globbing and word splitting.
> |Did you mean:
> |        if [ -f /var/lock/subsys/"$servicename" ]; then
> |
> |package/smcroute/S41smcroute:0: This file does not need to be executable, just make sure you use '$(INSTALL) -D -m 0755' in the .mk file
> |package/c-icap/S96cicap:0: run 'shellcheck' and fix the warnings
> |In package/c-icap/S96cicap line 12:
> |< tab  >[ $? == 0 ] && echo "OK" || echo "FAIL"
> |          ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
> |             ^-- SC2039: In POSIX sh, == in place of = is undefined.
> |
> |package/polkit/S50polkit:0: This file does not need to be executable, just make sure you use '$(INSTALL) -D -m 0755' in the .mk file
> |
> |package/polkit/S50polkit:0: run 'shellcheck' and fix the warnings
> |In package/polkit/S50polkit line 43:
> |< tab  >start|stop|restart|reload)
> |                           ^----^ SC2221: This pattern always overrides a later one on line 45.
> |In package/polkit/S50polkit line 45:
> |< tab  >reload)
> |        ^----^ SC2222: This pattern never matches because of a previous pattern on line 43.
> |
> |package/restorecond/S02restorecond:0: run 'shellcheck' and fix the warnings
> |In package/restorecond/S02restorecond line 52:
> |< tab  >< tab  >echo $"Usage: $0 {start|stop|restart|reload}"
> |                     ^-- SC2039: In POSIX sh, $".." is undefined.
> |
> |package/earlyoom/S02earlyoom:0: run 'shellcheck' and fix the warnings
> |In package/earlyoom/S02earlyoom line 10:
> |start() {
> |        ^-- SC1009: The mentioned syntax error was in this brace group.
> |In package/earlyoom/S02earlyoom line 11:
> |< tab  >printf() 'Starting %s: ' "$DAEMON"
> |        ^-- SC1073: Couldn't parse this function. Fix to allow more checks.
> |                 ^-- SC1064: Expected a { to open the function definition.
> |                 ^-- SC1072:  Fix any mentioned problems and try again.
> |
> |package/watchdogd/S01watchdogd:0: This file does not need to be executable, just make sure you use '$(INSTALL) -D -m 0755' in the .mk file
> |
> |package/brltty/S10brltty:0: run 'shellcheck' and fix the warnings
> |In package/brltty/S10brltty line 17:
> |restart() {
> |^-- SC2120: restart references arguments, but none are ever passed.
> |
> |package/audit/S02auditd:0: run 'shellcheck' and fix the warnings
> |In package/audit/S02auditd line 13:
> |CONFIG=/etc/audit/auditd.conf
> |^----^ SC2034: CONFIG appears unused. Verify use (or export if used externally).
> |
> |package/network-manager/S45network-manager:40: consecutive empty lines
> |package/network-manager/S45network-manager:41: consecutive empty lines
> |package/network-manager/S45network-manager:41: empty line at end of file
> |
> |package/tftpd/S80tftpd-hpa:0: run 'shellcheck' and fix the warnings
> |In package/tftpd/S80tftpd-hpa line 11:
> |PIDFILE=/var/run/$NAME.pid
> |^-----^ SC2034: PIDFILE appears unused. Verify use (or export if used externally).
> |
> |package/owfs/S60owfs:0: run 'shellcheck' and fix the warnings
> |In package/owfs/S60owfs line 1:
> |NAME="owfs"
> |^-- SC2148: Tips depend on target shell and yours is unknown. Add a shebang.
> |
> |package/owfs/S55owserver:0: run 'shellcheck' and fix the warnings
> |In package/owfs/S55owserver line 1:
> |NAME="owserver"
> |^-- SC2148: Tips depend on target shell and yours is unknown. Add a shebang.
> |
> |package/transmission/S92transmission:0: run 'shellcheck' and fix the warnings
> |In package/transmission/S92transmission line 50:
> |DAEMON=$(which $NAME)
> |         ^---^ SC2230: which is non-standard. Use builtin 'command -v' instead.
> 
> Ricardo Martincoski (5):
>    utils/check-package: prepare to run external tools
>    utils/checkpackagelib: warn about executable files
>    utils/checkpackagelib/lib_sysv: check SysV init scripts
>    support/docker: add shellcheck
>    utils/checkpackagelib/lib_sysv: run shellcheck
> 
>   support/docker/Dockerfile              |   1 +
>   utils/check-package                    |  39 ++++++--
>   utils/checkpackagelib/base.py          |  11 +++
>   utils/checkpackagelib/lib_config.py    |   1 +
>   utils/checkpackagelib/lib_hash.py      |   1 +
>   utils/checkpackagelib/lib_mk.py        |   1 +
>   utils/checkpackagelib/lib_patch.py     |   1 +
>   utils/checkpackagelib/lib_sysv.py      |  67 +++++++++++++
>   utils/checkpackagelib/test_lib_sysv.py | 131 +++++++++++++++++++++++++
>   utils/checkpackagelib/test_tool.py     | 112 +++++++++++++++++++++
>   utils/checkpackagelib/tool.py          |  23 +++++
>   11 files changed, 382 insertions(+), 6 deletions(-)
>   create mode 100644 utils/checkpackagelib/lib_sysv.py
>   create mode 100644 utils/checkpackagelib/test_lib_sysv.py
>   create mode 100644 utils/checkpackagelib/test_tool.py
>   create mode 100644 utils/checkpackagelib/tool.py
> 
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-02-06 17:29 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-26 18:49 [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck) Ricardo Martincoski
2021-12-26 18:49 ` [Buildroot] [PATCH 1/5] utils/check-package: prepare to run external tools Ricardo Martincoski
2021-12-26 18:49 ` [Buildroot] [PATCH 2/5] utils/checkpackagelib: warn about executable files Ricardo Martincoski
2021-12-26 18:49 ` [Buildroot] [PATCH 3/5] utils/checkpackagelib/lib_sysv: check SysV init scripts Ricardo Martincoski
2021-12-26 18:49 ` [Buildroot] [PATCH 4/5] support/docker: add shellcheck Ricardo Martincoski
2022-01-09 10:52   ` Romain Naour
2021-12-26 18:49 ` [Buildroot] [PATCH 5/5] utils/checkpackagelib/lib_sysv: run shellcheck Ricardo Martincoski
2022-02-06 17:29 ` [Buildroot] [PATCH 0/5] check-package for SysV init scripts (including shellcheck) Arnout Vandecappelle

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.