From af460cb43179366184e7ecce01d5d540a1f3f65c Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sat, 13 Jun 2026 22:15:02 -0300 Subject: [PATCH 1/6] shellhub-rootfs-postcommand: Add task docstring and tidy whitespace Make the class pass oelint-adv: * document the rootfs postprocess function with a [doc] flag (oelint.task.docstrings), * drop the trailing blank and use double quotes in the ROOTFS_POSTPROCESS_COMMAND append (oelint.var.rootfspostcmd), * remove the duplicate blank line (oelint.newline.consecutive), * suppress oelint.bbclass.underscores inline, as the dash in the class name is harmless here (no EXPORT_FUNCTIONS). No functional change. --- classes/shellhub-rootfs-postcommand.bbclass | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/classes/shellhub-rootfs-postcommand.bbclass b/classes/shellhub-rootfs-postcommand.bbclass index c36a38b..8c24f2f 100644 --- a/classes/shellhub-rootfs-postcommand.bbclass +++ b/classes/shellhub-rootfs-postcommand.bbclass @@ -1,3 +1,4 @@ +# nooelint: oelint.bbclass.underscores oelint.file.inlinesuppress_na no EXPORT_FUNCTIONS here, so the dash is harmless # Allow overriding of ShellHub Tenant ID # # Required variable: @@ -9,9 +10,9 @@ # # Copyright 2021 (C) O.S. Systems Software LTDA. - # Override the TENANT_ID from existing ShellHub configuration file. -ROOTFS_POSTPROCESS_COMMAND += 'shellhub_override_tenant_id ;' +ROOTFS_POSTPROCESS_COMMAND += "shellhub_override_tenant_id;" +shellhub_override_tenant_id[doc] = "Override the ShellHub TENANT_ID in the rootfs config from SHELLHUB_ROOTFS_TENANT_ID." shellhub_override_tenant_id () { if [ ! -e "${IMAGE_ROOTFS}${sysconfdir}/default/shellhub-agent" ]; then bbfatal "'${sysconfdir}/default/shellhub-agent' doesn't exist." From 461ec65a7fbdba3111f95f0f6457869fff803e81 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sat, 13 Jun 2026 22:15:07 -0300 Subject: [PATCH 2/6] packagegroup-shellhub: Add metadata and simplify RDEPENDS * set DESCRIPTION (mandatory), BUGTRACKER and SECTION, * collapse the single-entry RDEPENDS into a plain assignment, which also drops the leading blank flagged by oelint.vars.inconspaces and oelint.vars.notneededspace. No functional change. --- recipes-core/packagegroups/packagegroup-shellhub.bb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/recipes-core/packagegroups/packagegroup-shellhub.bb b/recipes-core/packagegroups/packagegroup-shellhub.bb index af5e716..379b868 100644 --- a/recipes-core/packagegroups/packagegroup-shellhub.bb +++ b/recipes-core/packagegroups/packagegroup-shellhub.bb @@ -1,4 +1,7 @@ SUMMARY = "ShellHub runtime support" +DESCRIPTION = "Packagegroup pulling in the ShellHub agent and its runtime dependencies." +BUGTRACKER = "https://github.com/shellhub-io/shellhub/issues" +SECTION = "console/network" LICENSE = "MIT" @@ -6,6 +9,4 @@ inherit packagegroup PACKAGES += "${PN}-runtime" -RDEPENDS:${PN}-runtime += " \ - shellhub-agent \ -" +RDEPENDS:${PN}-runtime = "shellhub-agent" From cbb68245fd99d007ccf9ac38f45b21325ccd20b4 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sat, 13 Jun 2026 22:15:18 -0300 Subject: [PATCH 3/6] shellhub-agent-config: Version the recipe and fix oelint-adv findings * rename to shellhub-agent-config_1.0.bb so the filename carries a version (oelint.file.underscores); PN is unchanged, so the RDEPENDS references to shellhub-agent-config keep resolving, * set DESCRIPTION, HOMEPAGE, BUGTRACKER and SECTION, * generate the configuration with an echo block instead of a tab-indented here-doc, dropping oelint.tabs.notabs and oelint.task.heredocs, * document the genuinely-not-applicable rules inline: the missing SRC_URI and CVE_PRODUCT (this recipe generates its config and ships no code), the layer-internal LIC_FILES_CHKSUM (oelint.var.licenseremotefile) and the parse-time SkipRecipe anonymous python (oelint.task.noanonpython). The generated configuration file is identical; no functional change. --- .../shellhub/shellhub-agent-config.bb | 31 --------------- .../shellhub/shellhub-agent-config_1.0.bb | 38 +++++++++++++++++++ 2 files changed, 38 insertions(+), 31 deletions(-) delete mode 100644 recipes-core/shellhub/shellhub-agent-config.bb create mode 100644 recipes-core/shellhub/shellhub-agent-config_1.0.bb diff --git a/recipes-core/shellhub/shellhub-agent-config.bb b/recipes-core/shellhub/shellhub-agent-config.bb deleted file mode 100644 index 8f171ed..0000000 --- a/recipes-core/shellhub/shellhub-agent-config.bb +++ /dev/null @@ -1,31 +0,0 @@ -SUMMARY = "ShellHub Configuration" -LICENSE = "MIT" -LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" -INHIBIT_DEFAULT_DEPS = "1" - -do_patch[noexec] = "1" -do_configure[noexec] = "1" - -SHELLHUB_SERVER_ADDRESS ??= "https://cloud.shellhub.io" -SHELLHUB_PRIVATE_KEY ??= "${sysconfdir}/shellhub-agent.key" -SHELLHUB_TENANT_ID ??= "undefined" - -python () { - if d.getVar("SHELLHUB_TENANT_ID", False) == "undefined": - raise bb.parse.SkipRecipe("To enable ShellHub support, the 'SHELLHUB_TENANT_ID' variable must be set.") -} - -do_compile () { - cat <<- EOF > shellhub-agent.default - SERVER_ADDRESS="${SHELLHUB_SERVER_ADDRESS}" - PRIVATE_KEY="${SHELLHUB_PRIVATE_KEY}" - TENANT_ID="${SHELLHUB_TENANT_ID}" - EOF -} - -do_install () { - # Install the global configuration - install -Dm 0644 shellhub-agent.default ${D}${sysconfdir}/default/shellhub-agent -} - -PACKAGE_ARCH = "${MACHINE_ARCH}" diff --git a/recipes-core/shellhub/shellhub-agent-config_1.0.bb b/recipes-core/shellhub/shellhub-agent-config_1.0.bb new file mode 100644 index 0000000..792f579 --- /dev/null +++ b/recipes-core/shellhub/shellhub-agent-config_1.0.bb @@ -0,0 +1,38 @@ +# nooelint: oelint.var.mandatoryvar.SRC_URI oelint.var.suggestedvar.CVE_PRODUCT config recipe: it generates its config inline (no SRC_URI) and ships no code to CVE-track +SUMMARY = "ShellHub Configuration" +DESCRIPTION = "Generates the global ShellHub agent configuration (server address, private key path and tenant ID)." +HOMEPAGE = "https://shellhub.io" +BUGTRACKER = "https://github.com/shellhub-io/shellhub/issues" +SECTION = "console/network" +LICENSE = "MIT" +# nooelint: oelint.var.licenseremotefile layer-internal recipe, no upstream source to carry a license file +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" +INHIBIT_DEFAULT_DEPS = "1" + +do_patch[noexec] = "1" +do_configure[noexec] = "1" + +SHELLHUB_SERVER_ADDRESS ??= "https://cloud.shellhub.io" +SHELLHUB_PRIVATE_KEY ??= "${sysconfdir}/shellhub-agent.key" +SHELLHUB_TENANT_ID ??= "undefined" + +# nooelint: oelint.task.noanonpython required to SkipRecipe at parse time +python () { + if d.getVar("SHELLHUB_TENANT_ID", False) == "undefined": + raise bb.parse.SkipRecipe("To enable ShellHub support, the 'SHELLHUB_TENANT_ID' variable must be set.") +} + +do_compile () { + { + echo "SERVER_ADDRESS=\"${SHELLHUB_SERVER_ADDRESS}\"" + echo "PRIVATE_KEY=\"${SHELLHUB_PRIVATE_KEY}\"" + echo "TENANT_ID=\"${SHELLHUB_TENANT_ID}\"" + } > shellhub-agent.default +} + +do_install () { + # Install the global configuration + install -Dm 0644 shellhub-agent.default ${D}${sysconfdir}/default/shellhub-agent +} + +PACKAGE_ARCH = "${MACHINE_ARCH}" From 350df8f6c84812226092724b8353342ececd182c Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sun, 14 Jun 2026 00:01:19 -0300 Subject: [PATCH 4/6] shellhub-agent: Add metadata and fix oelint-adv findings * set DESCRIPTION, BUGTRACKER and SECTION, * drop the leading blank in SRC_URI (oelint.vars.notneededspace), * use 'install -d' instead of 'mkdir -p' in do_install (oelint.task.nomkdir), * order the RDEPENDS entries alphabetically and place RDEPENDS before RRECOMMENDS (oelint.vars.dependsordered, oelint.var.order), * suppress oelint.task.network inline, as the go modules are fetched during do_compile by design. No functional change. --- recipes-core/shellhub/shellhub-agent_0.25.1.bb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/recipes-core/shellhub/shellhub-agent_0.25.1.bb b/recipes-core/shellhub/shellhub-agent_0.25.1.bb index bfb25f7..ffbd21f 100644 --- a/recipes-core/shellhub/shellhub-agent_0.25.1.bb +++ b/recipes-core/shellhub/shellhub-agent_0.25.1.bb @@ -1,10 +1,13 @@ SUMMARY = "ShellHub Agent" +DESCRIPTION = "ShellHub agent: enables remote SSH access to Linux devices behind firewall or NAT." HOMEPAGE = "https://shellhub.io" +BUGTRACKER = "https://github.com/shellhub-io/shellhub/issues" +SECTION = "console/network" LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://${S}/src/${GO_IMPORT}/LICENSE.md;md5=fa818a259cbed7ce8bc2a22d35a464fc" DEPENDS = "libxcrypt" -SRC_URI = " \ +SRC_URI = "\ git://github.com/shellhub-io/shellhub;protocol=https;nobranch=1;destsuffix=${GO_SRCURI_DESTSUFFIX} \ file://shellhub-agent.initd \ file://shellhub-agent.profile.d \ @@ -34,11 +37,12 @@ GO_LDFLAGS = '-ldflags="${GO_RPATH} ${GO_LINKMODE} -X main.AgentVersion=v${PV} - GOBUILDFLAGS:append = " -modcacherw" do_compile[dirs] += "${B}/src/${GO_IMPORT}/agent" +# nooelint: oelint.task.network go modules are fetched during compile do_compile[network] = "1" do_install:append() { # We name the binary as shellhub-agent - mkdir -p ${D}${libexecdir}/shellhub/bin/ + install -d ${D}${libexecdir}/shellhub/bin/ mv ${D}${bindir}/agent ${D}${libexecdir}/shellhub/bin/shellhub-agent # Handle init system integration @@ -66,9 +70,9 @@ do_install:append() { RDEPENDS:${PN} += "\ openssh-scp \ - shellhub-agent-config \ shadow \ + shellhub-agent-config \ " +RDEPENDS:${PN}-dev += "bash" RRECOMMENDS:${PN} += "ca-certificates" -RDEPENDS:${PN}-dev += "bash" From b7da36c375a6377796fd95c45ad27b2b006a6080 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sun, 14 Jun 2026 00:01:19 -0300 Subject: [PATCH 5/6] shellhub-agent: Set CVE_PRODUCT for cve-check The recipe name (shellhub-agent) does not match the product name ShellHub is tracked under in the NVD, so cve-check would not associate any CVE with this recipe. Set CVE_PRODUCT = "shellhub" so its CVEs are reported. This also satisfies oelint.var.suggestedvar.CVE_PRODUCT. --- recipes-core/shellhub/shellhub-agent_0.25.1.bb | 1 + 1 file changed, 1 insertion(+) diff --git a/recipes-core/shellhub/shellhub-agent_0.25.1.bb b/recipes-core/shellhub/shellhub-agent_0.25.1.bb index ffbd21f..6a818c6 100644 --- a/recipes-core/shellhub/shellhub-agent_0.25.1.bb +++ b/recipes-core/shellhub/shellhub-agent_0.25.1.bb @@ -3,6 +3,7 @@ DESCRIPTION = "ShellHub agent: enables remote SSH access to Linux devices behind HOMEPAGE = "https://shellhub.io" BUGTRACKER = "https://github.com/shellhub-io/shellhub/issues" SECTION = "console/network" +CVE_PRODUCT = "shellhub" LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://${S}/src/${GO_IMPORT}/LICENSE.md;md5=fa818a259cbed7ce8bc2a22d35a464fc" DEPENDS = "libxcrypt" From 82a765850e62a094c257311679d4316f28661eab Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sat, 13 Jun 2026 22:17:00 -0300 Subject: [PATCH 6/6] oelint: Add oelint-adv lint tooling and CI gate Add the declarative oelint-adv setup shared across the OEL layers: * .oelint.cfg pins the release (wrynose) and the only layer-wide suppression, oelint.var.bbclassextend, which never applies to a target-only layer, * oelint.constants.json declares the project distro/machine override tokens oelint cannot know when run standalone, * contrib/oelint/run-oelint.sh enumerates the recipes and runs the linter serially, * .github/workflows/oelint.yaml runs it on pull requests, merge groups and master pushes through the yocto-env.nix lint devshell. The layer lints clean, with every remaining exception documented inline as a '# nooelint: ' comment, so the gate is blocking. --- .github/workflows/oelint.yaml | 25 +++++++++++++++++++++++++ .oelint.cfg | 6 ++++++ contrib/oelint/run-oelint.sh | 23 +++++++++++++++++++++++ oelint.constants.json | 11 +++++++++++ 4 files changed, 65 insertions(+) create mode 100644 .github/workflows/oelint.yaml create mode 100644 .oelint.cfg create mode 100755 contrib/oelint/run-oelint.sh create mode 100644 oelint.constants.json diff --git a/.github/workflows/oelint.yaml b/.github/workflows/oelint.yaml new file mode 100644 index 0000000..ec334d7 --- /dev/null +++ b/.github/workflows/oelint.yaml @@ -0,0 +1,25 @@ +name: OE Lint + +on: + pull_request: + merge_group: + push: + branches: + - master + +concurrency: + group: ${{ github.repository }}-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + oelint: + runs-on: ubuntu-latest + steps: + - uses: ossystems/nix-actions@v1 + with: + install-nix: true + flake-check: false + build-hosts: false + build-devshells: false + devshell: github:OSSystems/yocto-env.nix#lint + run: ./contrib/oelint/run-oelint.sh diff --git a/.oelint.cfg b/.oelint.cfg new file mode 100644 index 0000000..647a719 --- /dev/null +++ b/.oelint.cfg @@ -0,0 +1,6 @@ +# oelint-adv defaults, auto-loaded from the working directory. Every recipe +# here is target-only, so oelint.var.bbclassextend never applies; all other +# exceptions stay inline as '# nooelint: ' comments. +[oelint] +release = wrynose +suppress = oelint.var.bbclassextend diff --git a/contrib/oelint/run-oelint.sh b/contrib/oelint/run-oelint.sh new file mode 100755 index 0000000..09c0562 --- /dev/null +++ b/contrib/oelint/run-oelint.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# Run oelint-adv over meta-shellhub. Requires oelint-adv on PATH. +# +# Configuration is declarative and lives at the layer root: .oelint.cfg +# (--release plus the bbclassextend suppression) and oelint.constants.json +# (the layer constant-DB additions). Both are auto-loaded, so this script only +# enumerates the files to lint. +set -eu + +unset CDPATH + +here=$(cd -- "$(dirname -- "$0")" && pwd) +layer=$(cd -- "$here/../.." && pwd) +cd -- "$layer" + +files=$(find . \ + \( -name '*.bb' -o -name '*.bbappend' -o -name '*.bbclass' -o -name '*.inc' \) \ + | sort) + +# Run serially: parallel workers race while loading the layer constants and +# emit spurious "unknown variable/override" findings. Pass '--jobs N' to override. +# shellcheck disable=SC2086 +exec oelint-adv --jobs 1 "$@" $files diff --git a/oelint.constants.json b/oelint.constants.json new file mode 100644 index 0000000..b53d86d --- /dev/null +++ b/oelint.constants.json @@ -0,0 +1,11 @@ +{ + "comment": "Layer constant DB, auto-loaded by oelint-adv from the layer root. Declares the OEL project distro/machine override tokens it cannot know about when run standalone.", + "replacements": { + "distros": [ + "oel" + ], + "machines": [ + "arm" + ] + } +}