From 7e914cbca69414c24ac091450c160ae70f51ab47 Mon Sep 17 00:00:00 2001 From: Alexandra Bara Date: Mon, 16 Mar 2026 11:42:33 -0500 Subject: [PATCH 1/3] README updates --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7cdfc78..1e46dff 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ system debug. - ['run-plugins' sub command](#run-plugins-sub-command) - ['gen-plugin-config' sub command](#gen-plugin-config-sub-command) - ['compare-runs' subcommand](#compare-runs-subcommand) - - ['show-redfish-oem-allowable' subcommand](#show-redfish-oem-allowable-subcommand) - ['summary' sub command](#summary-sub-command) - [Configs](#configs) - [Global args](#global-args) @@ -63,17 +62,20 @@ options are available: usage: node-scraper [-h] [--sys-name STRING] [--sys-location {LOCAL,REMOTE}] [--sys-interaction-level {PASSIVE,INTERACTIVE,DISRUPTIVE}] [--sys-sku STRING] [--sys-platform STRING] [--plugin-configs [STRING ...]] [--system-config STRING] [--connection-config STRING] [--log-path STRING] [--log-level {CRITICAL,FATAL,ERROR,WARN,WARNING,INFO,DEBUG,NOTSET}] [--gen-reference-config] [--skip-sudo] - {summary,run-plugins,describe,gen-plugin-config} ... + {summary,run-plugins,describe,gen-plugin-config,compare-runs,show-redfish-oem-allowable} ... node scraper CLI positional arguments: - {summary,run-plugins,describe,gen-plugin-config} + {summary,run-plugins,describe,gen-plugin-config,compare-runs,show-redfish-oem-allowable} Subcommands summary Generates summary csv file run-plugins Run a series of plugins describe Display details on a built-in config or plugin gen-plugin-config Generate a config for a plugin or list of plugins + compare-runs Compare datamodels from two run log directories + show-redfish-oem-allowable + Fetch OEM diagnostic allowable types from Redfish LogService (for oem_diagnostic_types_allowable) options: -h, --help show this help message and exit @@ -340,8 +342,8 @@ node-scraper compare-runs path1 path2 --include-plugins DmesgPlugin --dont-trunc You can pass multiple plugin names to `--skip-plugins` or `--include-plugins`. -#### **'show-redfish-oem-allowable' subcommand** -The `show-redfish-oem-allowable` subcommand fetches the list of OEM diagnostic types supported by your BMC (from the Redfish LogService `OEMDiagnosticDataType@Redfish.AllowableValues`). Use it to discover which types you can put in `oem_diagnostic_types_allowable` and `oem_diagnostic_types` in the Redfish OEM diag plugin config. +#### **Discovering allowable OEM diagnostic types** +The `show-redfish-oem-allowable` command fetches the list of OEM diagnostic types supported by your BMC (from the Redfish LogService `OEMDiagnosticDataType@Redfish.AllowableValues`). Use it to discover which types you can put in `oem_diagnostic_types_allowable` and `oem_diagnostic_types` in the Redfish OEM diag plugin config. **Requirements:** A Redfish connection config (same as for RedfishOemDiagPlugin). From b0fd81f92b247c1c8685499833967f48058472a4 Mon Sep 17 00:00:00 2001 From: Alexandra Bara Date: Mon, 16 Mar 2026 11:44:56 -0500 Subject: [PATCH 2/3] undid change --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1e46dff..33929f9 100644 --- a/README.md +++ b/README.md @@ -342,8 +342,8 @@ node-scraper compare-runs path1 path2 --include-plugins DmesgPlugin --dont-trunc You can pass multiple plugin names to `--skip-plugins` or `--include-plugins`. -#### **Discovering allowable OEM diagnostic types** -The `show-redfish-oem-allowable` command fetches the list of OEM diagnostic types supported by your BMC (from the Redfish LogService `OEMDiagnosticDataType@Redfish.AllowableValues`). Use it to discover which types you can put in `oem_diagnostic_types_allowable` and `oem_diagnostic_types` in the Redfish OEM diag plugin config. +#### **'show-redfish-oem-allowable' subcommand** +The `show-redfish-oem-allowable` subcommand fetches the list of OEM diagnostic types supported by your BMC (from the Redfish LogService `OEMDiagnosticDataType@Redfish.AllowableValues`). Use it to discover which types you can put in `oem_diagnostic_types_allowable` and `oem_diagnostic_types` in the Redfish OEM diag plugin config. **Requirements:** A Redfish connection config (same as for RedfishOemDiagPlugin). From 8c6769eab209db4eb4913b7444faf09187502a71 Mon Sep 17 00:00:00 2001 From: Alexandra Bara Date: Mon, 16 Mar 2026 14:09:13 -0500 Subject: [PATCH 3/3] automated updating the README output through doc generation script --- .github/workflows/update-plugin-docs.yml | 5 +- README.md | 42 +++++++++----- docs/generate_plugin_doc_bundle.py | 73 +++++++++++++++++++++++- 3 files changed, 104 insertions(+), 16 deletions(-) diff --git a/.github/workflows/update-plugin-docs.yml b/.github/workflows/update-plugin-docs.yml index d0b977a..a4da869 100644 --- a/.github/workflows/update-plugin-docs.yml +++ b/.github/workflows/update-plugin-docs.yml @@ -38,7 +38,8 @@ jobs: source venv/bin/activate python docs/generate_plugin_doc_bundle.py \ --package nodescraper.plugins.inband \ - --output docs/PLUGIN_DOC.md + --output docs/PLUGIN_DOC.md \ + --update-readme-help - name: Clean pre-commit cache run: | @@ -50,7 +51,7 @@ jobs: run: | source venv/bin/activate pre-commit install-hooks || true - pre-commit run --files docs/PLUGIN_DOC.md || true + pre-commit run --files docs/PLUGIN_DOC.md README.md || true - name: Create Pull Request uses: peter-evans/create-pull-request@v6 diff --git a/README.md b/README.md index 33929f9..ed60391 100644 --- a/README.md +++ b/README.md @@ -58,11 +58,18 @@ Sets up pre-commit hooks for code quality checks. On Debian/Ubuntu, you may need The Node Scraper CLI can be used to run Node Scraper plugins on a target system. The following CLI options are available: + ```sh -usage: node-scraper [-h] [--sys-name STRING] [--sys-location {LOCAL,REMOTE}] [--sys-interaction-level {PASSIVE,INTERACTIVE,DISRUPTIVE}] [--sys-sku STRING] - [--sys-platform STRING] [--plugin-configs [STRING ...]] [--system-config STRING] [--connection-config STRING] [--log-path STRING] - [--log-level {CRITICAL,FATAL,ERROR,WARN,WARNING,INFO,DEBUG,NOTSET}] [--gen-reference-config] [--skip-sudo] - {summary,run-plugins,describe,gen-plugin-config,compare-runs,show-redfish-oem-allowable} ... +usage: cli.py [-h] [--version] [--sys-name STRING] + [--sys-location {LOCAL,REMOTE}] + [--sys-interaction-level {PASSIVE,INTERACTIVE,DISRUPTIVE}] + [--sys-sku STRING] [--sys-platform STRING] + [--plugin-configs [STRING ...]] [--system-config STRING] + [--connection-config STRING] [--log-path STRING] + [--log-level {CRITICAL,FATAL,ERROR,WARN,WARNING,INFO,DEBUG,NOTSET}] + [--gen-reference-config] [--skip-sudo] + {summary,run-plugins,describe,gen-plugin-config,compare-runs,show-redfish-oem-allowable} + ... node scraper CLI @@ -75,32 +82,41 @@ positional arguments: gen-plugin-config Generate a config for a plugin or list of plugins compare-runs Compare datamodels from two run log directories show-redfish-oem-allowable - Fetch OEM diagnostic allowable types from Redfish LogService (for oem_diagnostic_types_allowable) + Fetch OEM diagnostic allowable types from Redfish + LogService (for oem_diagnostic_types_allowable) -options: +optional arguments: -h, --help show this help message and exit - --sys-name STRING System name (default: ) + --version show program's version number and exit + --sys-name STRING System name (default: ) --sys-location {LOCAL,REMOTE} Location of target system (default: LOCAL) --sys-interaction-level {PASSIVE,INTERACTIVE,DISRUPTIVE} - Specify system interaction level, used to determine the type of actions that plugins can perform (default: INTERACTIVE) + Specify system interaction level, used to determine + the type of actions that plugins can perform (default: + INTERACTIVE) --sys-sku STRING Manually specify SKU of system (default: None) --sys-platform STRING Specify system platform (default: None) --plugin-configs [STRING ...] - built-in config names or paths to plugin config JSONs. Available built-in configs: AllPlugins, NodeStatus (default: None) + built-in config names or paths to plugin config JSONs. + Available built-in configs: NodeStatus, AllPlugins + (default: None) --system-config STRING Path to system config json (default: None) --connection-config STRING Path to connection config json (default: None) - --log-path STRING Specifies local path for node scraper logs, use 'None' to disable logging (default: .) + --log-path STRING Specifies local path for node scraper logs, use 'None' + to disable logging (default: .) --log-level {CRITICAL,FATAL,ERROR,WARN,WARNING,INFO,DEBUG,NOTSET} Change python log level (default: INFO) --gen-reference-config - Generate reference config from system. Writes to ./reference_config.json. (default: False) - --skip-sudo Skip plugins that require sudo permissions (default: False) - + Generate reference config from system. Writes to + ./reference_config.json. (default: False) + --skip-sudo Skip plugins that require sudo permissions (default: + False) ``` + ### Execution Methods diff --git a/docs/generate_plugin_doc_bundle.py b/docs/generate_plugin_doc_bundle.py index 0c2c839..915a355 100644 --- a/docs/generate_plugin_doc_bundle.py +++ b/docs/generate_plugin_doc_bundle.py @@ -28,12 +28,16 @@ python generate_plugin_doc_bundle.py \ --package /home/alexbara/node-scraper/nodescraper/plugins/inband \ --output PLUGIN_DOC.md + --update-readme-help + """ import argparse import importlib import inspect import os import pkgutil +import re +import subprocess import sys from pathlib import Path from typing import Any, Iterable, List, Optional, Type @@ -513,6 +517,44 @@ def render_analyzer_args_section(args_cls: type, link_base: str, rel_root: Optio return s +# Markers in README.md that bracket the node-scraper -h block (HTML comments, not rendered). +README_HELP_BLOCK_START = "" +README_HELP_BLOCK_END = "" + + +def update_readme_help(readme_path: Path) -> bool: + """ + Update the node-scraper -h output block in README.md. + The block must be wrapped with and . + """ + result = subprocess.run( + [sys.executable, "-m", "nodescraper.cli.cli", "-h"], + capture_output=True, + text=True, + cwd=readme_path.parent, + ) + if result.returncode != 0: + return False + help_text = result.stdout.strip() + # Redact hostname in --sys-name default so README does not show machine name + help_text = re.sub( + r"(--sys-name STRING\s+System name \(default: )\S+", + r"\g<1>)", + help_text, + ) + content = readme_path.read_text(encoding="utf-8") + start_idx = content.find(README_HELP_BLOCK_START) + end_idx = content.find(README_HELP_BLOCK_END) + if start_idx == -1 or end_idx == -1 or end_idx <= start_idx: + return False + # Replace the entire bracketed block (from start marker through end marker) + block_end = end_idx + len(README_HELP_BLOCK_END) + new_block = f"{README_HELP_BLOCK_START}\n```sh\n{help_text}\n```\n{README_HELP_BLOCK_END}" + new_content = content[:start_idx] + new_block + content[block_end:] + readme_path.write_text(new_content, encoding="utf-8") + return True + + def main(): ap = argparse.ArgumentParser( description="Generate Plugin Table and detail sections with setup_link + rel-root." @@ -521,6 +563,16 @@ def main(): "--package", default=DEFAULT_ROOT_PACKAGE, help="Dotted package or filesystem path" ) ap.add_argument("--output", default="PLUGIN_DOC.md", help="Output Markdown file") + ap.add_argument( + "--update-readme-help", + action="store_true", + help="Update the node-scraper -h output block in README.md (run from repo root or with correct cwd)", + ) + ap.add_argument( + "--readme", + default=None, + help="Path to README.md (default: README.md in current working directory)", + ) args = ap.parse_args() root = args.package @@ -601,7 +653,26 @@ def all_subclasses(cls: Type) -> set[type]: for a in args_classes: out.append(render_analyzer_args_section(a, LINK_BASE_DEFAULT, REL_ROOT_DEFAULT)) - Path(args.output).write_text("".join(out), encoding="utf-8") + repo_root = Path(__file__).resolve().parent.parent + output_path = Path(args.output) + if not output_path.is_absolute(): + output_path = repo_root / output_path + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_text("".join(out), encoding="utf-8") + + if args.update_readme_help: + readme_path = Path(args.readme) if args.readme else Path.cwd() / "README.md" + if not readme_path.is_file(): + readme_path = Path(__file__).resolve().parent.parent / "README.md" + if readme_path.is_file(): + if update_readme_help(readme_path): + print(f"Updated node-scraper -h block in {readme_path}") # noqa: T201 + else: + print(f"Could not find or update -h block in {readme_path}") # noqa: T201 + sys.exit(1) + else: + print(f"README not found: {readme_path}") # noqa: T201 + sys.exit(1) if __name__ == "__main__":